Angular 10, 3 levels of nested from group with array - javascript

First: This is the project link: https://stackblitz.com/edit/angular-kmadq6
So.. I have the testForm with 3 levels of formGroup, and the last formGroup is an array of formGroups.
(File app.component.ts)..
Thus, i want to click on checkbox and enable the price field.
I didn't know how to get the price control from array of this form group.
I know that i can disable it by using [attr.disable]="variable" but is it mixind TemplateDrivenForm with ReactiveForm, but, if don't have any way to disable it from ReactiveForm way, i'll use this.
Thank you!

Use the method "get". See that you can "concatenate" using dots to reach the control and how we use the "index" "i". perhafs this example help you to understand the reason because we use [formGroupName]="i" in .html
checkboxChange(event,i){
const enabled:boolean=this.testForm.get('price.rentPeriods.'+i+'.checked').value
const control=this.testForm.get('price.rentPeriods.'+i+'.price')
if (enabled)
control.enable()
else
control.disable()
}

You could retrieve the inner form array creating a getter for the form group first, and then accessing the array, as follows:
get InnerFormGroup(){ return this.testForm.controls.price as FormGroup; }
get InnerFormArray(){ return this.InnerFormGroup.controls.rentPeriods as FormArray; }
That way, you can access the array controls anywhere on your component:
onCheckboxSelect(){
this.InnerFormArray.controls; //here you can access the array controls and disable/enable them
}

Related

is there a way to detect the valueChanges for formArray which has been dynamically binded from array of objects in angular8

is there a way to detect if there are any valueChanges for the toggle buttons made to form array which has been binded from dynamic array of objects.
Here, i am getting this.agentDetailsList and this.detailsToggle from the api, if i am in edit mode, this.agentDetails array i am binding to the formArray by using this.detailsToggle as this array has been used to bind in the html for looping. Here even though i made changes to the formarray it is not reflecting.
Basically my requirement is that, if there is any change in this formarray toggles before clicking on save, then API must be called, if there are no changes then api request shouldnt be made. Here i am not able to use valueChanges or statusChanges as both are not working.
Help appreciated.
Thanks in advance
TS:
i have used reactive forms, and the values are getting assigned to the html and the reactive forms is due to the array of object. So, what ever action i perform there must be used for comparing objects with the existing object. So i have used one array of object comparison method. But here the previous value is also getting binded to the new value which has been assigned to the form.
I want the newly edited value and the old value as seperate so that i can compare if the object proerty values are diffrent then i can enable for save.
DEMO: DEMO
TS:
saveDetails() {
this.objectsAreSame(this.agentDetailsList, this.detailsToggle)
console.log(this.agentDetailsList);
console.log(this.detailsToggle);
console.log(this.objectsAreSame,"this.objectsAreSame")
}
}
FORM:
private settingsInfoForm() {
if (!this.agentDetailsList) {
// Add
this.agentSettingsInfoForm = this.FB.group({
agentToogles: this.FB.array([this.detailsToggle]),
});
// this.authService.setDetailsData(this.agentSettingsInfoForm);
} else {
// Edit
if (this.agentDetailsList) {
this.detailsToggle = this.agentDetailsList
this.agentSettingsInfoForm = this.FB.group({
agentToogles: this.FB.array([this.detailsToggle]),
})
}
let settingsInfo = this.agentSettingsInfoForm.valueChanges.subscribe(data => {
this.formEdit = true;
console.log('agentSettingsInfoForm', this.formEdit)
})
}
DEMO
the problem is that you has any FormArray.
//this has no sense
this.FB.array([this.detailsToogle])
Do you want to write ?
this.FB.array(this.detailsToggle.map(x=>this.FB.group(x)))
This is a FromArray of FormGroups
Any way, if you only want to change the boolValue, you don't need create a formArray so complex, you can simply
this.FB.array(this.detailsToggle.map(x=>x.boolValue))
this is FormArray of FormControls
When you has an FormArray is for manage a FormArray. You has some too complex as
<input type="checkbox" [checked]="toggleValue.boolValue" (change)="toggleValue.boolValue = $event.target.checked">
when can be like,e.g. is is a FromArray of FormControls
<input type="checkbox" [formControlName]="i">
Really, you need ask you what data you want get and what data you want change. Tip: Before write nothing in your .html write
<pre>
{{agentSettingsInfoForm.?value |json}}
</pre>

How to get checkbox value from localStorage

There is a page with a lot of different checkbox questions which then get submitted and populate the next page, this page however gets refreshed and the already annoyed potential client needs to go back and fill out the form again.
Now I have localstorage set up so he doesn't need to reselect all the checkbox again, he just needs to resubmit the form and his back in action.
How does one keep the values populated on the problem page so this fella doesn't have to go back to resubmit?
//SIZE SAVE
function save() {
localStorage.setItem('100', checkbox.checked);
var checkbox = document.getElementById('100');
localStorage.setItem('200', checkbox.checked);
var checkbox = document.getElementById('200');
//SIZE LOAD
function load() {
var checked = JSON.parse(localStorage.getItem('100'));
document.getElementById("100").checked = checked;
var checked = JSON.parse(localStorage.getItem('200'));
document.getElementById("200").checked = checked;
//THIS PAGE NEEDS THE CHECKMARK
echo get_site_url().
"/the/checkmark/selected/was/".$_POST['check_group'].
"/.png";
}
I think is much simple for now and especially for the feature if you write some code to make the management for all checkboxes form your form.
First of all it will be best if you group all your checkboxes into a single place.
Into a function like this you can declare all your checkbox selectors you want to save into the localStoarge (now you don't need to make variables for each selector into multiple places into your code)
function getCheckboxItems() {
return ['100', '200']
.map(function(selector) {
return {
selector: selector,
element: document.getElementById(selector)
}`enter code here`
});
}
Then to make things much simpler you can store all the values from the checkbox into a single object instead of save the result in multiple keys, in this way is much simpler to make management (let's say you want to erase all values or to update only a part)
The following function will take as argument all checkbox items from the function above, the point is the function above will return an array with the checkbox id and the checkbox element, than you just reduce all that array into this function into an single object containing all the ids and values, after this you just store the object into the localStorage
function serializeCheckboxes(elements) {
var container = elements.reduce(function (accumulator, item) {
accumulator[item.selector] = item.element.checked;
return accumulator;
}, {})
localStorage.setItem('container', JSON.stringify(container));
}
function save() {
var elements = getCheckboxItems();
serializeCheckboxes(elements);
}
After this you need another function who will read all the values from the localStorge and place them into your checkbox "checked" state
function readCheckboxes() {
var storage = localStorage.getItem('container'), //Your key
container = (storage) ? JSON.parse(storage) : {};
Object.keys(container).forEach(function(key) {
var element = document.getElementById(key);
if(element) {
element.checked = container[key];
}
});
}
This is just a simple service who can manage your problem but I think, for any additional changes you can customize this solution much simpler instead of keeping all into multiple variables, also if you add more checkbox elements into your application with this solution you just add the corresponding id into the array from the first function.
A live example here:
https://jsbin.com/xejibihiso/edit?html,js,output
localStorage has two main functions, getItem and setItem. For setItem you pass in a key and a value. If you write to that key again, it will rewrite that value. So in your case, if a box is checked you would do
localStorage.setItem("checkbox_value", true)
and when it is unchecked you would pass in false instead. To get the value you can look at using jQuery like so:
$(checkbox).is(':checked')
and use a simple if-else clause to pass in true or false. then when you reload your page, on $(document).ready() you can get the values using
localStorage.getItem(key)
and use JavaScript to set the check boxes values.
localStorage only allows you to store strings. What you can do is use a loop to create a string that has all the check boxes values separated by some delimiter. So, for example, if there are four check boxes with values true false false true your string would be "true\nfalse\nfalse\ntrue" where \n is the delimiter. then you can store that string in localStorage and when you retrieve it you can put all the values into an array like so:
array = localStorage.getItem(key).split('\n').
Then you can populate your check boxes with that newly retrieved array. Ask if anything needs clarification.

How to add new key/value pair element to an existing array?

var onHomePageLoaded = function(retMsg)
{
$scope.data = retMsg.data.records;
$scope.data.link : 'http://www.newwebsite.com'
}
After i have added link element (key/value) to the javascript object, i am not able to get the same in the HTML template
<div ng-repeat="record in data">
<a ng-href="{{record.link}}"> Click Here </a>
</div>
Javascript is a dynamic language. You can add properties to existing objects in a very simple way , like assigning a value to an existing property. Just add a new property
$scope.data.link = 'http://www.newwebsite.com'
if retMsg.data.records is an array, still you can add a property to $scope.data.
if you want different link for every object in array then, do this.
$scope.data.forEach(function(obj){
obj.link = "your custom link" // write your logic here to produce different link.
});
If data is an array you can use
$scope.data.push(yourData);
for example
$scope.data.push({link : 'http://www.newwebsite.com'});
Or if you want to access the objects inside the array and add them a key value pair you can do as follow:
// add the link to the first entry
$scope.data[0].link = 'http://www.newwebsite.com';
Sorry. Do not know if I understood well.
Maybe you can define scope.data as:
$scope.data = {retMsg.data.records}
Then for example a function:
$scope.addNew = funtion(){
$scope.data.newElement = $scope.viewElement
};
In your HTML
<label>{{data}}</label> // Which makes reference to the $scope.data at the controller
<input ng-change="addNew()" ng-model="viewElement"></input>
<label>{{data.newElement}} // Will be empty at the very beginning but will show the new element once it is created.
Hope it helps
I see several issues with your code.
First, you use the variable name record in your ng-repeat, but then use report in ng-href. I assume those should be the same.
Also, link isn't a member of record, it is a member of data. You set it as a member of data here: $scope.data.link : 'http://www.newwebsite.com'. If you want to add that link to each record, in your onHomePageLoaded function, you'll need to loop through all the records you add to data, and add the link property to each one.

IN CQ, how to set value of all the items in Panel to blank

In ExtJS panel I need to set value of all items (e.g. textfield, pathfield) to blank. I don't want to set value of each individual item to blank but of whole panel in one go.
I am able to get list of items
function getAllChildren (panel) {
/*Get children of passed panel or an empty array if it doesn't have thems.*/
var children = panel.items ? panel.items.items : [];
/*For each child get their children and concatenate to result.*/
CQ.Ext.each(children, function (child) {
children = children.concat(getAllChildren(child));
});
return children;
}
but how to set to blank for whole panel? Please suggest what need to be done in this case.
Actually, it's not possible to do it with one liner - all at the same time. What your method returns is purely an array of objects. In fact if such syntax existed, it would iterate over all fields anyway.
Though clearing all fields, having the method you've proposed is very trivial to do. Just iterate over them all and call reset method. Mind some (especially custom) widgets might not handle it.
var fields = getAllChildren(panel);
CQ.Ext.each(fields, function(field) {
if (child.reset) {
child.reset();
}
});
You've got similar loop in your getAllChildren code - you might reset field at the same place.
The method is defined in Field type which is usually a supertype of each dialog widget. You can read more here.

Working with Data Attributes - Build a List & See if One Exists

I have 2 questions based on the graphic below:
How can I tell if one of the 'data-conversationmessageuserid' data attributes with a specific value exists - say 1000000003? I believe data selectors is what I need and have tried the following but its not working yet:
if($('#conversationsInBoxMessagesWrapperDIV')['data-conversationmessageuserid=1000000003']) {
// do something
}
How could I get all the 'data-conversationmessageuserid' data attributes into an array and the loop through them? I'm still playing with this code but its far from publishable. Trying to use .map
.map(function()
thankyou so much
Try:
if($('#conversationsInBoxMessagesWrapperDIV [data-conversationmessageuserid=1000000003]').length)
or
$('#conversationsInBoxMessagesWrapperDIV').find('[data-conversationmessageuserid=1000000003]') //Or children only to look at one level.
To get all the data values you could do:
var conversationmessageuserids = $('#conversationsInBoxMessagesWrapperDIV').children().map(function(){
return $(this).data('conversationmessageuserid');
}).get();
jQuery supports data attributes: http://api.jquery.com/data/
So you could do if($('#conversationsInBoxMessagesWrapperDIV').data('conversationmessageuserid') === 1000000003)

Categories