为什么其中一个AngularJS组件成功显示ng-model的值,而另一个不成功?

时间:2017-04-12 18:03:40

标签: javascript angularjs angular-ngmodel angular-components

我正在尝试创建一系列可以导入到一个主要组件中的动态组件。当我将所有对象传递到一个绑定而不是为每个传递的对象创建多个绑定时,将组件嵌入组件中要容易得多。所以我创造了一个傻瓜来展示我想要实现的目标。理想情况下,我希望能够将父组件中的对象传递到子组件的ng模型中,而无需创建单独的绑定。

这是否可能,有人可以向我提供任何建议或解释,说明为什么嵌套组件只在本地而不是在整个视图中更新模型?

基本上,如果你看下面的plunkr,我想让cNestedComponent以与cDirectComponent相同的方式运行,其中数据绑定从组件模板内部和模板外部更新。

http://plnkr.co/edit/vusx9rm1DnkbBlNBGyZG?p=preview

MARKUP:

<h1> Data Comment => {{ data.comment }} </h1>
<c-direct-input plplaceholder="direct component" plmodel="data.comment" pltype="text"></c-direct-input>
<c-nested-input input-bindings="{type: 'text', model: 'data.comment', placeholder: 'nested component'}"></c-nested-input>

组件:

app.component('cNestedInput', {
  template: '\
    <h2> Nested Component </h2>\
    <p style="display: block;"> {{ $ctrl.inputBindings.model }} </p>\
    <input type="{{ $ctrl.inputBindings.type }}" placeholder="{{$ctrl.inputBindings.placeholder}}" ng-model="$ctrl.inputBindings.model" />\
  ',
  bindings: {
    inputBindings: '='
  },
  controller: function($scope) {}
});

app.component('cDirectInput', {
  template: '\
    <h2> Direct Component </h2>\
    <p style="display: block;"> {{ $ctrl.plmodel }} </p>\
    <input type="{{ $ctrl.pltype }}" placeholder="{{ $ctrl.plplaceholder }}" ng-model="$ctrl.plmodel" />\
  ',
  bindings: {
    plplaceholder: '@',
    plmodel: '=',
    pltype: '@'
  },
  controller: function($scope) {}
});

=============================================== =========

更新

根据用户Julien Tassin的反馈,我创建了一个更新的更新的plunker,我认为更好地展示了我的目标:

https://plnkr.co/edit/cvYAdB?p=preview

直接组件示例是实现我的目标的明确方法,但我不必在组件彼此嵌套时列出每个单独的绑定。例如:

<c-nested-input input-bindings="$ctrl.input.inputBindings"/>
输入

后输入

要容易得多

<c-direct-input input-placeholder="{{$ctrl.inputPlaceholder}}" input-type="{{$ctrl.inputType}}" input-model="$ctrl.inputModel"/>\

每次我想将输入组件嵌套在父组件中时。

希望此更新能够进一步澄清我正在寻找的内容。

1 个答案:

答案 0 :(得分:0)

有几个问题会让你的例子不起作用:

第一期:不可转让的财产

你有一个&#34;不可转让&#34;问题。当您声明<c-nested-input input-bindings="{type: 'text', model: 'data.comment', placeholder: 'nested component'}"></c-nested-input>时,您创建了一个不可分配的属性{type: 'text', model: 'data.comment', placeholder: 'nested component'}(顺便说一下,'data.comment'上的data.comment错误应该是{{1} }})。当你试图在ngModel中为它赋值时,它会失败,因为你不能影响一个不可赋值的表达式,即使是一个不可赋值的表达式属性

因此,解决方案是在主控制器中设置可分配对象inputBindings并将其传递给组件。

第二次发布data.comment参考

那不是全部。 如果您尝试:

  $scope.data = {}
  $scope.inputBindings = {
    type: 'text',
    model: $scope.data.comment,
    placeholder: 'nested component'
  }

并将其传递给您的嵌套组件:

<c-nested-input input-bindings="inputBindings"></c-nested-input>

它不会按你的意愿工作。 因为当你的嵌套会修改inputBindings.model时,它不会是与data.comment相同的引用。 =绑定表示inputBindings而不是其属性。

没有办法避免这种情况。

所以你必须放弃data.comment并按照以下方式工作:

MARKUP:

<body ng-controller="MainCtrl">
  <h1> Data Comment => {{ inputBindings.model }} </h1>
  <hr/>
  <c-direct-input plplaceholder="direct component" plmodel="inputBindings.model" pltype="text"></c-direct-input>
  <c-nested-input input-bindings="inputBindings"></c-nested-input>
</body>

JS:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.inputBindings = {
    type: 'text',
    placeholder: 'nested component'
  }
});

app.component('cNestedInput', {
  template: '\
    <h2> Nested Component </h2>\
    <p style="display: block;"> {{ $ctrl.data.comment }} </p>\
    <input type="{{ $ctrl.inputBindings.type }}" placeholder="{{ $ctrl.inputBindings.placeholder}}" ng-model="$ctrl.inputBindings.model" />\
  ',
  bindings: {
    inputBindings: '='
  },
  controller: function() {}
});

app.component('cDirectInput', {
  template: '\
    <h2> Direct Component </h2>\
    <p style="display: block;"> {{ $ctrl.plmodel }} </p>\
    <input type="{{ $ctrl.pltype }}" placeholder="{{ $ctrl.plplaceholder }}" ng-model="$ctrl.plmodel" />\
  ',
  bindings: {
    plplaceholder: '@',
    plmodel: '=',
    pltype: '@'
  },
  controller: function() {

  }
});

plunker中的示例。

我的建议

我认为创建组件的更简洁方法是混合方法:

类似的东西:

JS:

app.component('cHybridInput', {
  template: '\
    <h2> Nested Component </h2>\
    <p style="display: block;"> {{ $ctrl.data.comment }} </p>\
    <input type="{{ $ctrl.options.type }}" placeholder="{{ $ctrl.options.placeholder}}" ng-model="$ctrl.ngModel" />\
  ',
  bindings: {
    ngModel: '=',
    options: '<'
  },
  controller: function() {}
});

HTML:

<c-hybrid-input ng-model="inputBindings.model" options="inputBindings"></c-hybrid-input>