简体   繁体   English

绑定 <select>使用ng-options和ng-model,其中模型具有组合键

[英]Bind <select> with ng-options and ng-model where model has composite key

I have an Angular service that returns a list of objects that have a "composite" key made up of two parts. 我有一个Angular服务,该服务返回具有“复合”键的对象列表,该键由两部分组成。 I don't see how I can write the bindings so that they properly re-bind existing data. 我看不到如何编写绑定,以便它们正确地重新绑定现有数据。 Here's my current attempt: 这是我目前的尝试:

 angular.module("app", []) .controller("fooCtrl", function() { // This comes from an Angular service / back-end: this.options = [ { part1: 3, part2: 101, displayName: "Option 3-101" }, { part1: 4, part2: 651, displayName: "Option 4-651" }, { part1: 4, part2: 999, displayName: "Option 4-999" } ]; this.item = { selectedOption: { part1: 4, part2: 651 } }; }); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script> <div ng-app="app" ng-controller="fooCtrl as vm"> <select ng-options="option.displayName for option in vm.options track by part1 + '-' + part2" ng-model="vm.item.selectedOption"></select> <hr> Debug info: <pre>{{vm.item | json}}</pre> </div> 

However, the above does not work: it should be selecting "Option 4-651" on loading, but doesn't do this. 但是,以上操作无效:加载时应选择"Option 4-651" ,但不能执行此操作。

Note that the displayName is added client side to the options, but it is not in the selectedOption when it is loaded. 请注意, displayName是在客户端添加到选项的,但是在加载时不在 selectedOption I don't mind if the selectedOption becomes an object that does have the displayName property, the back-end will just ignore it anyways because there is no equivalent backing property for it (I use C# in the back-end, the server-side DTO has no displayName property). 我不介意selectedOption变成一个确实具有displayName属性的对象,无论如何后端都将忽略它,因为没有等效的支持属性(我在服务器端的后端使用C# DTO没有displayName属性)。

Important: I'm trying to do this without changing the loading in the javascript and structure of the options and selectedOption . 重要提示:我正在尝试执行此操作, 而不更改javascript的加载以及optionsselectedOption结构。 Specifically: 特别:

  • I understand I can put some logic at the end of the controller method to "reset" this.item to a reference to the actual entry in options , but in my real code it's not so trivial (for one because async loading of options and selectedOption is involved). 我知道我可以在控制器方法的末尾放置一些逻辑来“重置” this.item ,以引用对options实际条目的引用,但是在我的真实代码中,它并不是那么简单(因为一个是异步加载的options和selectedOption,参与了)。
  • I also understand I could change both the selectedOption and individual options so the "composite key" is also available as a "single compound key" eg part1and2: "3-101" , but this requires me to admit (knowing that) I have an XY-Problem: I can't easily change the structure of those, because I'm cheating by binding my UI to the DTOs coming from the back-end, instead of having a proper view model to bridge the gap. 我也知道我可以更改selectedOption和单个options因此“复合键”也可以作为“单个复合键”使用,例如part1and2: "3-101" ,但这需要我承认(知道)我有一个XY问题:我无法轻易更改它们的结构,因为我通过将UI绑定到来自后端的DTO来作弊,而不是使用适当的视图模型来弥补差距。

Is there a way to do this with a track by expression, ie is there a way to elegantly solve this in the binding expressions? 是否有一种方法可以track by表达式track by ,即是否可以在绑定表达式中优雅地解决此问题? Or do I have to resort to fixing this in controller or service code? 还是我必须在控制器或服务代码中解决此问题?

一个简单的解决方案是,在绑定JavaScript对象之前对其进行重组,以使其具有另一个名为part12属性,然后按该属性进行跟踪:)

If the displayName is part of the JSON response then you should add that aswell to the selectedOption when you set the option in the controller. 如果displayName是JSON响应的一部分,则在控制器中设置选项时,也应将其添加到selectedOption中。

Here's a working example of how you could do it without it (if you have the display name in the default selectedOption then add "option as option.displayName.." instead) 这是一个没有它的方法的工作示例(如果您的显示名称位于默认的selectedOption中,请添加“ option as option.displayName ..”)

 angular.module("app", []) .controller("fooCtrl", function() { // This comes from an Angular service / back-end: this.options = [ { part1: 3, part2: 101, displayName: "Option 3-101" }, { part1: 4, part2: 651, displayName: "Option 4-651" }, { part1: 4, part2: 999, displayName: "Option 4-999" } ]; this.item = { selectedOption: { part1: 4, part2: 651} }; }); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script> <div ng-app="app" ng-controller="fooCtrl as vm"> <select ng-options="option as ('Option ' + option.part1 + '-' + option.part2) for option in vm.options track by (option.part1 +'-'+ option.part2)" ng-model="vm.item.selectedOption"></select> <hr> Debug info: <pre>{{vm.item | json}}</pre> </div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM