【问题标题】:Can't set selected value of ng-options无法设置 ng-options 的选定值
【发布时间】:2016-08-03 21:39:18
【问题描述】:

我正在尝试填充下拉选择选项列表并使用 ng-model 和 ng-options 设置默认选择值。

我认为有以下代码:

<select ng-model="thisTour.site" ng-options="site.name for site in siteList"></select>

在我的控制器中:

    $scope.siteList = [
        { id: 1, name: 'cycling'},
        { id: 2, name: 'walking'},
        { id: 3, name: 'holidays'}
    ]

    $scope.thisTour.site = { id: 2, name: 'walking'};

列表中填充了来自 siteList 对象的正确 3 个选项,但它没有像我期望的那样默认选择 walking?为什么不呢?

现在,当我改变这个时:

$scope.thisTour.site = { id: 2, name: 'walking'};

到这里:

$scope.thisTour.site = $scope.siteList[1];

现在可以了。为什么?不是一样的吗?

【问题讨论】:

    标签: angularjs angularjs-ng-options


    【解决方案1】:

    这是因为 Angular 会寻找对象相等性以将其与您的语法绑定,并且在您的情况下,$scope.siteList[1] 不等于 { id: 2, name: 'walking'};(只有当它们指向相同的引用时,两个对象才相等)。您可以通过多种方式解决此问题,一种简单的方法是使用 track by 语法和 ng-options 来通过 id 指定轨道,这将使 ng-option 的选项可以通过绑定对象的指定属性来跟踪,而不是而不是对象引用本身。

    <select ng-model="thisTour.site" 
        ng-options="site.name for site in siteList track by site.id"></select>
    

    您还可以使用语法将 ng-model 设置为仅指定 id,使用语法中的 select as 部分:-

    例子:-

    ng-options="site.id as site.name for site in siteList"
    

    而模型只是:-

     $scope.thisTour.site = 2;
    

    angular.module('app', []).controller('ctrl', function($scope){
      $scope.thisTour = {};
     $scope.siteList = [
            { id: 1, name: 'cycling'},
            { id: 2, name: 'walking'},
            { id: 3, name: 'holidays'}
        ]
    
        $scope.thisTour.site = { id: 2, name: 'walking'};
    })
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div ng-app="app" ng-controller="ctrl">
      <select ng-model="thisTour.site" ng-options="site.name for site in siteList track by site.id"></select>
      {{thisTour.site}}
      </div>

    来自documentation

    trackexpr: - 在处理对象数组时使用。此表达式的结果将用于识别数组中的对象。 trackexpr 很可能会引用 value 变量(例如 value.propertyName)。这样,即使重新创建选项(例如从服务器重新加载),选择也会保留。

    另外值得注意的是:

    不要在同一个表达式中使用 select as 和 track by。它们不是为协同工作而设计的。

    【讨论】:

    • 好的,我想我现在明白了,谢谢。我顺便读过“跟踪”,但没有完全理解。很全面,谢谢。
    • @Inigo 是的,文档链接已关闭。查看官方 ng-options 文档中的用法部分。
    • +1 Do not use select as and track by in the same expression. They are not designed to work together
    • 谢谢kazupooot,你的评论对我很有用。
    【解决方案2】:

    这不是一回事,因为 javascript 中的对象通过引用传递

    如果你举第一个例子:

    $scope.siteList = [
        { id: 1, name: 'cycling'},
        { id: 2, name: 'walking'},
        { id: 3, name: 'holidays'}
    ]
    
    $scope.thisTour.site = { id: 2, name: 'walking'};
    

    然后你这样做:

    $scope.thisTour.site.id = 3;
    console.log($scope.siteList[1].id) // 2
    

    换句话说,虽然您的两个对象的 相同,但它们不是同一个对象。 ngOptions 指令会看到这一点,因此会将 thisTour.site 设置为空白值,因为它不是允许的选项之一。

    谷歌“在 javascript 中通过引用传递”以了解更多信息。

    【讨论】:

    • 我想它应该是引用的副本,我认为 javascript 中没有任何引用传递。 Incase of objects 对象的引用被复制...它与许多语言中的 by ref 实现完全不同。
    • 不确定我是否理解您的评论。这超出了我的编程知识。我读过的所有 javascript 书籍都说 javascript 通过引用传递对象。
    • function updateObj(someObj){someObj = null;}var ob = {test:'1'}; updateObj(ob); 这不会使对象 someObj 无效,因为复制到函数的是对象引用的值。而在支持使用 ref 关键字的引用传递的 c# 中说,原始对象反过来将被取消。
    • 我真的在为绑定下拉选择的值而苦苦挣扎,但你的解决方案真的很简单,对我有帮助。谢谢先生发布这么简单的解决方案
    【解决方案3】:

    由于您在选择中使用了整个对象,因此当 Angular 进行比较时,它将查看对象是否相同以便设置您的选择。我相信有一种方法可以改变 Angular 如何进行比较的功能,但我只是循环选择并进行类似于下面的自己的比较:

    $scope.siteList = [
            { id: 1, name: 'cycling'},
            { id: 2, name: 'walking'},
            { id: 3, name: 'holidays'}
        ]
    angular.forEach($scope.siteList, function(site, index) {
        if (site.id == 2) {
            $scope.thisTour.site = site;
        }
    });
    

    这会将实际对象设置为您的变量,以便在选择中设置它。

    【讨论】:

      【解决方案4】:

      使用 ng-init 指令。它是在初始化时执行的,我们可以为 ng-model 赋值。

      <div ng-init="thisTour.site = siteList[position]">
          <select ng-model="thisTour.site" ng-options="site.name for site in  siteList track by site.id"></select>
      </div>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-07
        • 2018-02-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多