【问题标题】:ng-model not updated from controller to viewng-model 未从控制器更新到视图
【发布时间】:2016-10-21 05:38:25
【问题描述】:

in this plunk我已经为我上周面临的问题做了一个演示。代码 sn-p 包含引导选项卡,其中包括两个不同的页面 - page1page2 并且它们使用 same 控制器。 Page1 有 ng-repeat,当我们从那里点击选项时,它会在控制器函数 vm.edit(selected_variable) 中被命中,并且 Page2 有一个简单的输入框,其中有一个 ng-model=" vm.name”。我的问题是当 vm.edit 函数更新它时,ng-name 没有更新或替换为该值。我可以使用 rootScope 解决这个问题,但我不想使用 rootScope。我只是想避免 rootScope 并想使用 vm

我的代码示例:

第 1 页:

<div ng-controller="appCtrl as vm">
  <div>
    <ul>
      <li ng-repeat="list in vm.list track by $index">
        <button type="button" class="btn-u btn-brd btn-u-none" ng-click="vm.edit(list, $index)" data-toggle="tab" href="#page2">
                    {{ list.name }}
                </button>
      </li>
    </ul>
  </div>
</div> 

第 2 页:

<div ng-controller="appCtrl as vm">
  <input type="text" ng-model="vm.name">
</div>

控制器:

vm.edit = function(listItem, index) {
    vm.name = listItem.name;

    console.log(vm.name);
  };

编辑功能会更新 page1 中的 vm.name,但不会反映在 page2 中。无法解决这个问题,有什么想法吗?

【问题讨论】:

    标签: javascript angularjs twitter-bootstrap


    【解决方案1】:

    为了控制器之间的通信,你可以利用 $broadcast 事件来传输数据。这是编辑后的Plunker

    vm.edit函数内注册广播并在同一个控制器中监听事件:

    vm.edit = function(listItem, index) {
      $rootScope.$broadcast("vm name: changed", listItem.name);
    };
    $scope.$on("vm name: changed", function(evt, obj){
      vm.name = obj;
    });
    

    另外不要忘记将 $rootScope 依赖项添加到您的控制器:

    app.controller('appCtrl', function($scope, $rootScope) {...});
    

    注意:这里的$rootScope只用于触发事件,不用于存储值。

    【讨论】:

      【解决方案2】:

      page1.html

      <div ng-controller="appCtrl">
      <div>
      <ul>
        <li ng-repeat="listitem in list track by $index">
          <button type="button" class="btn-u btn-brd btn-u-none" ng-click="edit(listitem, $index)" data-toggle="tab" href="#page2">
            {{ listitem.name }}
          </button>
        </li>
      </ul>
      </div>
      </div>
      

      page2.html

      <div ng-controller="appCtrl">
      <div>
      <ul>
        <li ng-repeat="listitem in list track by $index">
          <button type="button" class="btn-u btn-brd btn-u-none" ng-click="edit(listitem, $index)" data-toggle="tab" href="#page2">
            {{ listitem.name }}
          </button>
        </li>
      </ul>
      </div>
      </div>
      

      script.js

      var app = angular.module('app', []);
      app.controller('appCtrl', function($scope, $compile) {
      var vm = this;
      // List
      $scope.list = [
        {
          'id': 1,
          'name': 'afroza'
        },
        {
          'id': 2,
          'name': 'yasmin'
        }
      ];
      // edit function
      $scope.edit = function(listItem, index) {
      
      
          $scope.name = listItem.name;
      
          //this one is very important
          $compile(angular.element( document.querySelector('#name')))($scope);
      
      };
      
      });
      

      Please check Demo

      【讨论】:

        【解决方案3】:

        page1 and page2 and they are using same controller - 他们没有使用相同的控制器。他们正在使用同一控制器的两个不同实例。

        如果你想使用相同的 Controller 实例,你可以在 parent 上做ng-controller="appCtrl as vm"。否则,您可以使用rootScopeservice

        Demo

        【讨论】:

          【解决方案4】:

          您应该只添加两个组件,例如 PageComponent 和 PageContainerComponent。 PageContainerComponent 放在包含选项卡的母版页中。 PageComponent 需要 PageContainerComponent 作为父级并包含页面的逻辑。

          然后您可以简单地将任何您想要共享的内容放入 PageContainerComponent 中,因为 PageComponent 可以访问它。如果您甚至可以将内容直接绑定到页面视图中的 PageContainerComponent,前提是您将 PageContainerComponent 作为 PageComponent 上的变量提供。

          类似这样的:

          angular.module('app').component('pageContainerComponent', {
              controller: function() {
                  this.someProperty = 'yay';
              },
              template: '<div ng-transclude></div>'
          });
          
          angular.module('app').component('page1Component', {
              controller: function() {
                  // This controller will now have a property tabsCtrl
                  // With the controller for pageContainerComponent
              },
              controllerAs: 'vm',
              template: '<div>Page 1 content {{vm.tabsCtr.someProperty}}</div>',
              require: {
                 tabsCtrl: '^myTabs'
              },
          });
          

          用法应该是这样的

          <page-container-component>
              <div class="someTabClass">
                   <page1-component></page1-component>
              </div>
          </page-container-component>
          

          这都是我的想法,所以这里或那里可能有一个错字,但我希望它无论如何都会有所帮助。

          编辑

          哦,差点忘了,你当然可以对 page1Component 和 page2Component 使用相同的控制器函数,以创建多个具有相同控制器逻辑但视图不同的页面。不过我真的不明白这一点,因为“共享逻辑”无论如何都应该在 pageContainerComponent 中。

          【讨论】:

            猜你喜欢
            • 2012-09-19
            • 1970-01-01
            • 1970-01-01
            • 2018-10-11
            • 1970-01-01
            • 1970-01-01
            • 2016-11-04
            • 2015-11-06
            相关资源
            最近更新 更多