-
Notifications
You must be signed in to change notification settings - Fork 13.5k
fix(select): Added trackBy property to allow selecting the object by … #6627
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
Conversation
…property instead of by object equality (closes #6625)
Would you also be able to provide some unit tests to go along with this change? Thanks |
I'm having a lot of trouble creating unit tests for the select. I keep running into errors saying that there is no Provider for Form (Form is an interface, as well as a dependency that is supposed to be injected into the select constructor). Could you provide me some examples of unit tests for the ion-select? |
I think that you code is wrong. I haven't this issue. First: The values are objects works fine, but you can't use it in future, because an object pointer changes all time after initialization. So It hasn't the exact same values! Therefore you must added identification for your object. Second: Angular 2 trackBy requires a method and not a field.
|
The difference between your code and mine is this: <ion-select [(ngModel)]="chosenCurrency">
<ion-option *ngFor="let currency of currencies" [value]="currency">{{currency.name}}</ion-option>
</ion-select> The [value] of each ion-option is the actual object (currency), not a property in the object (currency.code). |
Of course! My code works, your doesn't :) You think, that it's Ionic issue, and I try to explain your, that your issue is not understanding how the javascript works. How Angular must compare your model with your value? A deep compare is very expansive. Angular uses hash pointer compare. But your object hash pointer changes all time. So where a bug? Therefore you could use key/id of object. Do you understand? |
Hello @xr0master, would you mind keeping our Code of Conduct in mind when interacting with others? Thanks! |
I understand how the Javascript works and why my code doesn't work. But for my specific needs, I cannot use a key/id as the value, and I require the value to be the object itself. Currently, that is not supported, unless I am missing something. My PR simply provides that functionality. |
@jgw96 you are right, I don't see more meaning to try to teach something others, it's not worth it. I only hope that the library does not turn into the trash of useless code. |
@xr0master I would like to understand. If I am truly wrong, please show me. This is the codepen that shows the problem. If you can make it work the way I am talking about, please show me. |
I feel like this needs some attention. I still have the same problem as before. If anyone feels that this is not a good fix, then how do I accomplish what I would like to do? |
@xr0master your use case seems to not be the same use case that @zakton5 have. He doesn't want to store the currency.code in chosenCurrency variable, but the entire currency object. This why your code works and his code don't. Different meaning and different purpose. Angular2 supports this feature in https://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta14-2016-04-07 Discussions about this here: And here: This type of feature is crucial when your are working on cascading select boxes and when you have model oriented forms.
|
@cleever I didn't say that his code is wrong, I only think that the place of code is wrong. I think, code that we can very easy implement in our controller, must be out of common library. I, you and he need the feature, but another 100 people no need it. However each added feature increases a weight of library and also decreases a performance. IMHO Example: <ion-select [(ngModel)]="chosenCurrency" (change)="changedCurrency()">
<ion-option *ngFor="let currency of currencies" [value]="currency.id">{{currency.name}}</ion-option>
</ion-select> class MyController {
private currencyObject: any;
public chosenCurrency: string;
public currencies: Array<any>;
controller() {}
public changedCurrency(): void {
this.currencyObject = this.currencies[this.chosenCurrency];
}
} It's easy, isn't it? PS I'm sorry about my terrible English. |
@cleever, angular does support this but not for my specific use case. I am pulling my pre-selected objects from a database. Therefore, the list of objects in my component, and the actual object used for the model value is a completely different object, even though it has the exact same properties. I ended up doing this, which is similar to @xr0master's solution. <ion-select [ngModel]="someProperty.id" (ngModelChange)="selectObjectById(list, $event, 'someProperty')">
<ion-option *ngFor="let item of list" [value]="item.id">{{item.name}}</ion-option>
</ion-select> public selectObjectById(list: any[], id: string, property: string) {
var item = list.find(item => item._id === id);
var prop = eval('this.' + property);
prop = property;
} This is essentially what the pull request did in the first place. It's unfortunate that this is necessary, but it works as desired. |
Short description of what this resolves:
ion-select currently cannot select the correct value if:
This is due the ion-select only wanting to select objects based on object equality.
Changes proposed in this pull request:
I'm open to other approaches. I've also considered just looking at each and every property within the object, but that seems expensive, especially if the object has many/nested properties
Usage:
Ionic Version: 2.x
Fixes: #6625