ng-model未从控制器更新到视图

时间:2016-10-21 05:38:26

标签: javascript angularjs twitter-bootstrap

in this plunk我已经为我上周面临的问题做了一个演示。代码段包含引导标签,其中包含两个不同的页面 - 第1页第2页,它们使用的是相同的控制器。 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);
  };

编辑功能会更新第1页中的 vm.name ,但它并未在第2页中反映出来。无法解决这个问题,任何想法?

4 个答案:

答案 0 :(得分:3)

为了在控制器之间进行通信,您可以使用 $ 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 仅用于触发事件,但不用于存储值。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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

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

Demo

答案 3 :(得分:0)

您应该添加两个组件,例如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使用相同的控制器函数,使多个页面具有相同的控制器逻辑,但视图不同。我不是真的明白这一点,因为共享逻辑&#39;无论如何都应该在pageContainerComponent中。