how to detect the checkbox checked event in formly angular7? - checkbox

Using formly and Json I created one form. Now I want display a text box when I checked the check box.
I tried with ngDoCheck() method, but I was unable to display the text. The box.this method hitted every field click event, although I need checked event only. Can any one help me out this.
"createConfig": [
{
"columnName": "chkid",
"columnSize": 50,
"columnType": 5,
"discreteValues": null,
"displayName": "",
"filterType": "e",
"isEnabled": 1,
"isMultiSelect": 0,
"isRequired": 0,
"isVisible": 1,
"listDataProvider": null,
"position": 2,
"showSuggestion": 1,
"sizeUnit": "px",
"useDisplayValueOnly": 1
},
{
"columnName":"nonusaddresa",
"displayName": "Address1/Address2/City/State/Zip/PostalCode/Country",
"position": 2,
"columnType": 1,
"isSortable": 0,
"defaultSortOrder": null,
"columnSize": 800,
"sizeUnit": "px",
"isVisible": 0,
"isEnabled": 1,
"isRequired": 0,
"isMultiSelect": 0,
"showSuggestion": 1,
"useDisplayValueOnly": 1,
"filterType": "e",
}
]

Subscribe to valueChanges of form
<formly-form #formlyForm
[model]="configModel"
[fields]="fields">
</formly-form>
#ViewChild(FormlyForm) public formlyForm: FormlyForm;
public ngAfterViewInit() {
this.formlyForm.form.valueChanges
enter code here
}
Don't forget to unsubscribe:
.pipe(this.readUntilDestroyed())

I had the same problem.
Even in 2022, I had to find a workaround based on id generated by formly-form and the click event _ eg.
this.app.objects[0].data.presentation[2][0].templateOptions.click = (field, event) => {
if (event.target.firstChild.id === 'formly_9_multicheckbox_foo_0_5-input') { // the sixth checkbox
// Notice : it was inverted because the checked is before setting value
if (event.target.firstChild.checked) {
// enabled another field
this.app.objects[0].data.presentation[3][0].templateOptions.disabled = false;
} else {
// disabled another field
this.app.objects[0].data.presentation[3][0].templateOptions.disabled = true;
}
}
};
This example is with multicheckbox.

You need to have (change) event on input to see if the checkbox is checked or not
<input type="checkbox" (change)="checkMethod($event)">
In your ts file
checkMethod(event)
{
if(event.target && event.target.checked)
{
//this means input is checked
}
}

Related

Handle multiple radio buttons in a tree view with React

I have a dataset with menu items and nested sub-menu items, coming from a GET request. With that, I render a table in a react-hook-form for assigning access permissions on each menu item.
[
{
moduleId: 2,
moduleName: "Menu 1",
permission: 0,
subModuleList: [
{
moduleId: 7,
moduleName: "Menu 1.1",
permission: 0,
subModuleList: null
},
{
moduleId: 8,
moduleName: "Menu 1.2",
permission: 0,
subModuleList: [
{
moduleId: 11,
moduleName: "Menu 1.2.1",
permission: 0,
subModuleList: null
},
{
moduleId: 33,
moduleName: "Menu 1.2.2",
permission: 0,
subModuleList: null
},
{
moduleId: 49,
moduleName: "Menu 1.2.3",
permission: 0,
subModuleList: null
},
{
moduleId: 68,
moduleName: "Menu 1.2.4",
permission: 0,
subModuleList: null
}
]
}
]
}
]
Each table row is a menu item and has 2 radio buttons (no access & read) if it has children, and 3 radio buttons (no access, read & read/write) if is without children.
What I am trying to accomplish, is that each time a radio button is clicked on a child menu item, I want all the parent menu items to update as well with a relevant checked radio button. I feel really stacked on how to achieve this with react.
Here is a code sandbox link with all the current implementations.
Example use case: When checking the menu item Menu 1.2.2 with read or read/write permissions, the Menu 1.2 and Menu 1 should also have checked the read permission
Thank you in advance for your time!
So after some thought, I came up with a solution. The first step is to identify all the parents of each child is clicked.
function getPath(object, search) {
if (object.moduleId === search) return [object.moduleName];
else if (object.subModuleList || Array.isArray(object)) {
let children = Array.isArray(object) ? object : object.subModuleList;
for (let child of children) {
let result = getPath(child, search);
if (result) {
if (object.moduleId) result.unshift(object.moduleName);
return result;
}
}
}
}
This function returns an array of names of all the parent elements. Then I had to find these parent elements on my dataset and update their values based on my needs. There is also a check if the parent element has children, and one or more are checked with value > 0, to retain the parent as checked.
//get all parent objects
const findId = (object, key, searchTerm, newValue) => {
if (object === null) return;
if (Array.isArray(object)) {
for (const obj of object) {
findId(obj, key, searchTerm, newValue);
}
} else {
if (object.hasOwnProperty(key) && object[key] === searchTerm) {
if (object.subModuleList !== null) {
if (newValue >= "1") newValue = "1";
if (newValue === "0") {
const childActive = object.subModuleList.some(
(element) => element.permission !== "0"
);
if (childActive) {
newValue = "1";
} else {
newValue = "0";
}
}
}
object.permission = newValue;
return object;
}
for (const k of Object.keys(object)) {
if (typeof object[k] === "object") {
findId(object[k], key, searchTerm, newValue);
}
}
}
};
Here you can find an updated code sandbox
I hope that someone will benefit from this solution. Also, I want to mention that the code presented here, is also from answers of other devs on other topics.

Using jQuery to change css in option tags does not work until second click in Angular

I have a edit button that opens a bootstrap modal to edit a record:
<a href="#" ng-click="getAction(action.id, 'edit')"
data-toggle="modal" data-target="#modalEditAction"
class="functionalLinks">
<i class="glyphicon glyphicon-pencil"></i>
EDIT
</a>
getAction(action.id, 'edit') looks like this:
$scope.getAction = function (actionId, populateObject) {
$http.get(actionUrl + '/' + actionId)
.then(function (response) {
// Test front end exception message;
// throw "test exception";
switch (populateObject) {
case "details":
$scope.data.actionDetails = response.data;
break;
case "edit":
$scope.data.editAction = response.data;
$scope.dimAt1EditActionRecommendedByLerSelections();
break;
}
})
.catch(function (error) {
$scope.data.actionDetailsError = error;
});
}
So we are interested in the "edit" case of the switch:
The response data looks like this (Look at the actionsRecommendedByLer property):
{
"caseId": 8,
"case": null,
"actionTypeId": 1,
"actionType": {
"actionTypeName": "Actions Taken By Management",
"caseType": 1,
"id": 1
},
"dateCreated": "2017-05-08T14:55:23.797",
"actionStatus": 3,
"notes": "bngfhfrg455",
"actionType1Id": null,
"actionType1": {
"actionId": 1,
"actionsRecommendedByLer": [
{
"actionType1Id": 1,
"lookUpDetailId": 4,
"name": "Alternative Discipline Agreement in lieu of # day Suspension",
"id": 1
},
{
"actionType1Id": 1,
"lookUpDetailId": 7,
"name": "Arbitration",
"id": 2
},
{
"actionType1Id": 1,
"lookUpDetailId": 13,
"name": "Complaint - EEO Formal",
"id": 3
}
],
"actionProposedBySupervisorId": 4,
"actionProposedBySupervisor": {
"id": 4,
"displayValue": "Alternative Discipline Agreement in lieu of # day Suspension",
"code": "",
"parentId": null,
"externalSystemId": null,
"isInactive": false,
"inactivDate": null,
"sortOrder": null,
"discriminator": "",
"lookupMaster": null,
"lookUpMastersId": 1
},
"actionTakenBySupervisorId": 8,
"actionTakenBySupervisor": {
"id": 8,
"displayValue": "AWOL Letter (CORPS)",
"code": "",
"parentId": null,
"externalSystemId": null,
"isInactive": false,
"inactivDate": null,
"sortOrder": null,
"discriminator": "",
"lookupMaster": null,
"lookUpMastersId": 1
},
"actionCharges": [
{
"actionType1Id": 1,
"lookUpDetailId": 211,
"name": "Creating hostile work environment",
"id": 1
}
],
"actionEffectiveDate": "2017-05-16T04:00:00",
"id": 1
},
"actionType17Id": null,
"actionType17": null,
"id": 1
}
And I use the response data to show a table with detete buttons basically showing which Select Options are chosen like this:
<select class="pull-right" id="editActionRecommendedByLerSelect"
ng-model="data.editAction.actionType1.actionRecommendedByLerId">
#*<option value="0"></option>*#
<option value="{{managmentAction.id}}"
ng-repeat="managmentAction in data.managementActions">
{{managmentAction.displayValue}}
</option>
</select>
<br />
#*{{data.editAction.actionType1.actionRecommendedByLerId}}*#
<table class="table table-condensed table-bordered">
<tr ng-show="data.editAction.actionType1.actionsRecommendedByLer.length == 0">
<td colspan="2" class="noResultText">No Actions Recommended By LER</td>
</tr>
<tr ng-repeat="actionRecommendedByLer in data.editAction.actionType1.actionsRecommendedByLer">
<td>
<a href="#" ng-click="removeAnEditActionRecommendedByLerFromActionType1(actionRecommendedByLer.id)"
class="functionalLinks text-danger">
<i class="glyphicon glyphicon-trash"></i>
DELETE
</a>
</td>
<td>#*{{actionRecommendedByLer.id}} :*# {{actionRecommendedByLer.name}}</td>
</tr>
</table>
The select is populated by an array of choices. The choice ID will match the appropritate lookupDetailId of the actionRecommendedByLer id. in the collection.
This line in the "edit" case of the switch in $scope.getAction(actionId, populateObject):
$scope.dimAt1EditActionRecommendedByLerSelections();
calls this:
$scope.dimAt1EditActionRecommendedByLerSelections = function () {
console.log("In dimAt1EditActionRecommendedByLerSelections");
console.log("Length: " + $scope.data.editAction.actionType1.actionsRecommendedByLer.length);
var element;
for (i = 0; i < $scope.data.editAction.actionType1.actionsRecommendedByLer.length; i++) {
console.log("i: " + i);
console.log("id: " + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId);
element = $('#editActionRecommendedByLerSelect option[value = "' + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId + '"]');
element.attr('disabled', 'disabled');
element.css('background-color', 'yellow');
}
}
Basically I am using jQuery to make the multiple options already selected in the select drop down yellow and disabled. This was easy from my Add Bootstrap modal.
But loading it all back in for an edit and hightlighting the right ones is proving to be way more difficult.
This works and shows in the Select Drop Down the choice names highlighted in yellow and disabled in the model being rendered in a table next to a delete button. The only problem is it doesn't show the choices hightlighted until I click the edit button again.
How can I get this to hightlight and disable the options on the first edit click?
UPDATE 1 (In response to comment user1120808)
I tried your answer but it is not working. In fact now it does not even work on the second click.
Does this look like correct implementation of your suggestion?
$scope.dimAt1EditActionRecommendedByLerSelections = function () {
console.log("In dimAt1EditActionRecommendedByLerSelections");
console.log("Length: " + $scope.data.editAction.actionType1.actionsRecommendedByLer.length);
var element;
for (i = 0; i < $scope.data.editAction.actionType1.actionsRecommendedByLer.length; i++) {
console.log("i: " + i);
console.log("id: " + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId);
// force scope digest.
$scope.$evalAsync(() => {
element = $('#editActionRecommendedByLerSelect option[value = "' + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId + '"]');
element.attr('disabled', 'disabled');
element.css('background-color', 'yellow');
});
}
}
The reason you don't see it, is because jquery runs outside of angular and angular doesn't pick it up. It isn't evaluated anymore. But with the second click you trigger a digest cycle, so you see it then. So what you need to do is force a digest cycle. You can use $evalAsync for this.
try the following:
$scope.$evalAsync(() => {
element = $('#editActionRecommendedByLerSelect option[value = "' + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId + '"]');
element.attr('disabled', 'disabled');
element.css('background-color', 'yellow');
});
$timeout service solved the problem:
$scope.dimAt1EditActionRecommendedByLerSelections = function () {
console.log("In dimAt1EditActionRecommendedByLerSelections");
console.log("Length: " + $scope.data.editAction.actionType1.actionsRecommendedByLer.length);
$timeout(function() {
var element;
for (i = 0; i < $scope.data.editAction.actionType1.actionsRecommendedByLer.length; i++) {
console.log("i: " + i);
console.log("id: " + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId);
element = $('#editActionRecommendedByLerSelect option[value = "' + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId + '"]');
element.attr('disabled', 'disabled');
element.css('background-color', 'yellow');
}
}, 1000);
}

angularjs ng-repeater dynamically delete data

I have a situation where users added sample data as shown in figure. How can I add Delete button which deletes particular sample ONLY. From figure , I want 'Delete Sample 1" to delete Sample 1 records only.
Thanks
Code triggered when Add Sample button is clicked
$scope.addSample = function () {
$scope.partdetails = [
{
"sampleseq": 0,
"sampleid": 1,
"attribute": "Height",
"measureunit": "Centimeter",
"actualvalue": null,
"lowerspec": 1.23,
"upperspec": 3.23,
"notes": null
},
{
"sampleseq": 0,
"sampleid": 2,
"attribute": "Diameter",
"measureunit": "Inches",
"actualvalue": null,
"lowerspec": 1.23,
"upperspec": 3.23,
"notes": null
}
];
$scope.partdetails[0].sampleseq = $scope.sampleCount;
$scope.partdetails[1].sampleseq = $scope.sampleCount;
$scope.partdetailsList.push($scope.partdetails[0]);
$scope.partdetailsList.push($scope.partdetails[1]);
$scope.sampleCount += 1;
}
This link has the solution just modify the list accordinlgy
https://coderwall.com/p/fnp2oq/use-ng-repeat-on-tbody-to-create-summary-rows-for-nested-data
You can use Array.prototype.filter to get a new data record without the items that fail a predicate function
Lets say your delete button calls a function called deleteSample and passes it a sample id:
HTML:
... ng-repeat="row in records" ...
<button ng-click="deleteSample(row.sampleid)">Delete sample</button>
Controller:
$scope.deleteSample = function(sampleId) {
$scope.records = $scope.records.filter((row)=> {
return !angular.equals(sampleId, row.sampleid)
});
}
Of course that doesn't solve the issue that you would probably need to remove the rows in your db too.

Using ng-change in search box

Request :
$scope.viewAccount = function(){
var json = {
"json": {
"request": {
"servicetype": "60",
"functiontype": "1014",
"data": {
"shortname": $scope.model.selectShortName,
"groupzname": $scope.model.selectGname,
"city": $scope.model.selectCity,
"state": $scope.model.selectState,
"country": $scope.model.selectCountry,
"groupzcode": $scope.model.selectGcode,
"activationstatus": true,
"details": false,
"sortbasedon": $scope.groupzname,
"orderby": "desc",
"limit":10,
}
}
}
};
UserService.viewListAccount(json).then(function(response) {
console.log(JSON.stringify(json));
if (response.json.response.statuscode == 0 && response.json.response.statusmessage == 'Success')
{
$scope.tableData = response.json.response.data;
console.log($scope.tableData);
}
else{
alert(response.json.response.statusmessage);
}
});
};
The above function is to display all datas into table.I have a search box in groupzname,shortname and I used ng-change and called a new function changeviewAccount() removing offset in request. But the problem here I get is even if I enter one letter in searchbox, the function is getting called everytime. I am new to AngularjS .
Instead of ng-change , you can use ng-blur,whhich tells AngularJS what to do when an input box loses focus.
<input ng-blur="changeviewAccount()" type="text" class="form-control" placeholder="Title">

Using object property in select

I currently have the following select:
<select ng-model="current_event"
ng-options="event.event_id for event in current_level.events.event"
ng-change="currentEventChanged()">
</select>
current_level.events.event is an array of objects which looks like this:
[
{
"event_id": 0,
"event_type": {
"collision": {
"object_id1": 0,
"object_id2": 1,
"allow_overlap": "no"
}
}
},
{
"event_id": 1,
"event_type": {
"player_input": {
"object_id": 0,
"level_id": 0,
"allow_overlap": "no"
}
}
}
]
The select works perfectly, but the text for each option is just the event_id, e.g. "0" or "1". I want the text for an item to actually be the event_type (with underscores converted to spaces), e.g. "collision" or "player input". Is this possible in AngularJS?
You're using event.event_id, so there is nothing wrong in the behaviour of AngularJS. You should simply put the right label in the ng-options of <select> (see the documentation).
However, you need to call a function before in order to obtain the correct label, since what you want is pretty complex.
$scope.getLabel = function (eventType)
{
var firstKey = null;
angular.forEach(eventType, function (value, key)
{
if (firstKey === null)
{
firstKey = key;
}
});
return firstKey.replace('_', ' ', 'g');
};
<select
ng-model="current_event"
ng-options="event.event_id as getLabel(event.event_type) for event in current_level.events.event"
ng-change="currentEventChanged()"
>
</select>
jsFiddle

Resources