I'm experiencing a problem that has me stumped. I have an ng-select. When loading records to the ngModel, it doesn't change the ng-select. The weirdest part is that on another page, the same code works.
I've tried numerous different options, even creating new arrays just to test. Also tried setTimeout to see if something is clearing the selection.
The HTML code
<label>
Add a Secondary channel
</label>
<br />
<ng-select placeholder="Select schools" items="schoolsArray" [(ngModel)]="selectedSecondSchools" [multiple]="true" name="secondSchools"
#secondSchools="ngModel">
</ng-select>
</div>
The one function in the component. The array is declared as selectedSecondSchools[] = [];
getVodEventGameSecondaryChannels(vodEventId: number, vodEventGameId: number): string[] {
let schoolIds: string[] = [];
this.vodEventService
.getVodEventGameSecondaryChannelsByGameId(vodEventId, vodEventGameId)
.subscribe((sc: IVodEventGameSecondaryChannels[]) => {
sc.forEach(gsc => {
schoolIds.push(
gsc.schoolId.toString());
});
});
this.eventGame.gameSecondaryChannelIds = schoolIds;
this.selectedSecondSchools = schoolIds;
return schoolIds;
}
When the data is returned, the returned IDs need to be selected within the ng-select and displayed.
It depends on the type of schoolsArray. In your case, I guess, schoolsArray is a list of objects, while ngModel is an array of strings. ng-select doesn't know how to map strings from ngModel to objects from items.
Please see documentation for property bindValue to inform ng-select how to bind items keys to the model. https://github.com/ng-select/ng-select
To summarize, add bindValue="id-property-name-in-items" to ng-select tag.
Related
I use 3 mat-select for day-month-year selection as shown on this DEMO.
I need to make the first options as null or undefined and modify that code as shown below:
allDates: number[] = [null];
dates: number[] = [null];
months: number[] = [null];
years: number[] = [null];
But I am not sure if it is a good idea or is there a proper way for mat-select. I also try to set [value]=null for the mat-select options, but in that case it does not receive the value properly. So, what is a proper way for this?
Is there a reason they need to be null? In my opinion it is more confusing to have a blank option.
Play around with the stack blitz to see how it behaves when initialized as an empty array vs when it is bound to an array with one null item. I think the UX is great when the mat-select is bound to an empty array. The mat-label resides in the select box, easy to see what type of data is in the select. Also when you click it, it doesn't show any options, because there aren't any. If you have a null, then the dropdown opens with one blank item.
I don't think there is anything wrong with the code you provided.
Edit:
You can bind the mat-select item with an object and use a display property to show the text and a value property to bind to the actual value.
Say you have an interface like this:
export interface DateSelectItem
{
value: number;
label: string;
}
let dates: DateSelectItem[] = [
{
value: -1
label: "None"
}
];
selectedDate: DateSelectItem;
in the template:
<mat-form-field>
<mat-label>Date</mat-label>
<mat-select [(ngModel)]="selectedDate">
<mat-option *ngFor="let date of dates" [value]="date">
{{date.label}}
</mat-option>
</mat-select>
</mat-form-field>
You can use just strings and convert them back and forth with their number equivalents.
Or if you use an object you can use the label property to display something other than the value.
EDIT: Modified StackBlitz
You will probably need to update the business logic on what you want the resulting date to look like if the user selects 'None' for day-of-the-month.
Updated StackBlitz
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>
I have multiple input text checkbox. I want to store the change box event in an array and later when user submits the Save changes, it should be saved.
<td><input type="checkbox" class="switch" ng-model="each_value.at_enable_flag" ng-change="changeMyArray(each_value)"> </td>
The problem with this is, if a user toggle the check box(On/ Off), it stores both the entries not only the latest one.
I tried to remove the duplicates but that is also having some issue.
Can anyone please help me out how I can store the cehckbox value in an array only if the checkbox original value has changed.
Here is my plunkr. Please have a look and let me know if u need any more details.
https://plnkr.co/edit/ZE5xWhfpmbSXqflDs5Qv?p=preview
Simply store original value in separate property. Then compare with your model.
https://plnkr.co/edit/IAOUhH7tekTzl15uFi8N?p=preview
In your code.
$scope.toTemplate.forEach(function (value) {
value.default = value.at_enable_flag;
});
$scope.myArray = [];
$scope.saveAtData = function() {
$scope.myArray = $scope.toTemplate.filter(function (value) {
return value.default !== value.at_enable_flag;
});
console.log($scope.myArray);
$scope.saveValue = $scope.myArray;
}
There is no need for ng-change on input, as it would fire more than needed. Simply filtering array for changed values is enough.
I've tried looking for other stackOverflow posts, but none were working for me.
I have a JSONObject that resembles this:
{QRX23: {element: { ... } }, RIJ52: { model: } }
It's obviously much bigger, and has more information, but the main point is that each type of object doesn't have identical types of information, so I really cannot use an array or something here.
Now, I am trying to use ng-repeat and go through this object, and while using it i want to use the filter. I have a form inside my HTML document, and I want to filter the form's ng-model value to the current object's KEY (not value) while it is being traversed.
Thanks in advance for the help.
EDIT: Just to give more context, while I'm using ng-repeat, I, for example, iterate through each of the main items (such as QRX23) using ng-repeat. Then within this ng-repeat, I have another ng-repeat which should go through the keys within the main items.
Then, I want to filter these keys, and basically check, for example, if the main item has a key in the object called "element", it can be displayed.
<div ng-repeat="(observer, observerObj) in JSONbugs | filter:observerSelection" class="row">
<h5>{{observer}} </h5>
<div ng-repeat="(host, hostObj) in observerObj | filter:hostSelection" class="col-md-6" >
<h6>Host {{host}}</h6>
<div ng-repeat="(bug, times) in hostObj | filter: bugSelection">{{bug}}</div>
</div>
</div>
I am trying to use a filter that I have written in my controller to narrow down a select list using ng-options. The filter logic is working, but the results aren't getting displayed.
Here's the relevant part of my controller:
$scope.ESGFilter = function() {
var esg;
var filteredESGs = [];
// LOGIC GOES HERE TO POPULATE THE filteredESGs ARRAY
console.log(filteredESGs);
return filteredESGs;
}]);
Here's the HTML:
<select class="input-block-level" id="inputESG" name="inputStoch"
ng-model="Run.ESG"
ng-options="econ.Id as econ.Name for econ in econData | filter:ESGFilter" size="5">
</select>
I suspect the issue has to be with "filter:ESGFilter" in the HTML... I can't figure out why the array that I return from the function isn't being displayed. The function in the controller is definitely being called and the logic is working.
For reference, the console.log outputs: [Object, Object] -- when I expand the properties of these objects, I confirm that they are the ones that I want. The select list, however, displays all four objects (I'm filtering down from an array of four).
Your filter needs to return a true/false statement. Write your filter like this:
$scope.ESGFilter = function(item) {
// if you want to keep the item return true, else false
};
This works because the ngOptions takes each item in your array and passes it to your filter function. Your example is not working because it's returning an empty array which will always resolve to a truthy value, and all objects will be accepted and not filtered.
Here's a plunk:
http://plnkr.co/edit/RfKMcXDKy1m1EGyoEpS7?p=preview