-
Notifications
You must be signed in to change notification settings - Fork 26.3k
Provide customizable object comparison method for NgModel #13268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Would love to see this implemented, because I have many places in my application where dropdown values are loaded from a rest service dynamically, and they are represented by complex objects. Without a way to track them, I am forced to instead force singleton instances on the client-side, or write a custom input for the object which assigns the value of the |
As a temporary solution, I've written the following component, which allows the user to pass in a label for each option, and a field to track the options by: @Component({
'selector': 'trackable-select',
template:
`<select [ngModelOptions]="{standalone: true}" [disabled]="disabled" [required]="required" [ngModel]="_primativeValue" (ngModelChange)="onValueChange($event)">
<option value="">{{emptyLabel}}</option>
<option *ngFor="let option of options" [value]="trackValue(option)">{{getLabel(option)}}</option>
</select>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TrackableSelectComponent),
multi: true
}
]
})
export class TrackableSelectComponent extends BaseFormControlComponent {
private value: any
private _primativeValue: string | number
@Input()
required: boolean
@Input()
disabled: boolean
@Input()
options: any[]//the dropdown values
@Input()
label: string//the field of the option to use as the label
@Input()
trackBy: string//the field of the option to store as the value
@Input()
emptyLabel = '- Select -' //the empty option label
onValueChange($event) {
this._primativeValue = $event;
this.value = undefined;
for (let option of this.options) {
const optionTracker = this.trackValue(option);
if (optionTracker === $event) {
this.value = option;
break;
}
}
this.propagateChange(this.value);
this.onTouched();
}
writeValue(obj: any) {
this.value = obj;
this._primativeValue = this.trackValue(obj);
}
getLabel(option: any) {
return util.objectProperty(this.label, option);//returns object property by path.
}
trackValue(option: any) {
return util.objectProperty(this.trackBy, option);//returns object property by path.
}
} and can be used like this
|
Was there any reason why this was not applicable to radio inputs? |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
I'm submitting a ... (check one with "x")
Current behavior
Currently NgModel does object reference comparison. This is not very flexible.
Minimal reproduction of the problem with instructions
See example with two multi selects - first one doesn't use workaround to enforce usage of same instances. The second one does.
http://plnkr.co/edit/MND6j3Wa5ZDsIt9X9ZVQ?p=preview
What is the motivation / use case for changing the behavior?
Objects do not always come from the same source. They typically come from some REST service. And they usually don't have the same instance.
Current behavior requires workaround for something I believe to be very (if not the most) common use case. I think those should be supported by framework without requiring any workarounds.
Suggested solution
I suggest creating comparator object (or callback) which would compare two objects and return true if they are equal. NgModel would then internally use this comparator to compare objects.
Resulting code could look like this:
Framework could also provide some default comparators - for example one, which would compare object attributes. That one would be sufficient for quite a lot of use cases.
If there already is some standard solution, please point me to it. I tried to search and I didn't find anything. I found just this stack overflow post describing the same problem, but not providing any solution.
The text was updated successfully, but these errors were encountered: