ng模型没有从控制器更新到视图

ng-model not updated from controller to view

本文关键字:更新 视图 控制器 模型 ng      更新时间:2023-09-26

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

代码示例:

page1

:

<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> 
所以page2

:

<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中没有反映。无法解决这个问题,有什么主意吗?

为了在控制器之间通信,你可以使用$broadcast事件来传输数据。以下是编辑后的普朗克。

内的 vm。编辑函数注册广播并监听同一控制器中的事件:

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仅用于触发事件而不用于存储值

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);
};
});

请查看Demo

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

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

演示

您应该只添加两个组件,比如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无论如何。