【问题标题】:Angular write into nested scope properties角度写入嵌套范围属性
【发布时间】:2015-03-13 18:13:14
【问题描述】:

我的应用中有多个“输入字段和按钮”对。 该按钮会打开一个对话框,以便在文本字段中写入内容。

[ input ] [ button ] ---> [ dialog ( ok ) ( cancel ) ]

我使用过 Bootstrap.UI.Modal (https://angular-ui.github.io/bootstrap/#/modal),所以我承诺会处理它:

//html
<input ng-model="foo"/>
<button ng-click="dialog('foo')"> Open </button>

//controller
modalInstance.result.then(
    function ( selectedItem ) {
        $scope[ arg ] = selectedItem;
    }, 
    ...
);

一切正常。 (Demo) 当我必须访问作用域对象的嵌套属性时,问题就来了:

...
<input ng-model="foo"/>
<button ng-click="dialog('foo')"> Open </button>
...
<li ng-repeat="thing in model.nested.properties.of.unknown.level">
    ...
    <input ng-model="thing.foo"/>
    <button ng-click="dialog( '???' )"> Open </button>
    ...

我想知道的是:实现这一目标的最佳方法是什么?

直到现在我都尝试过:

  • 将作用域变量传递给返回的回调,但它只得到值,而不是引用;所以该字段不会被更新。

     resolve: {
         field: function() {
           return $scope[ field ];
         }
     }
    
  • 传递一个字符串数组来重新创建范围层次结构

     dialog( ["a","b","c"] ) --> $scope[ "a" ][ "b" ][ "c" ] = output.value;
    
  • 准备一个回调对象,例如

     object = { 
       "one": function(){ $scope.a.b.c = ... }, 
       "two": function(){ $scope.d.e.f = ... }, 
       ... 
       // but this requires that I know in advance 
       // how many level I will nest into the $scope
     }
    
  • 使用输入字段的id,所以你可以直接写入DOM(但据我所知这在angularjs中不是一个好方法)

     $("#input-abc...").val( ... )
    
  • 使用 eval (uungh...)

我认为第一个解决方案是最好的,但是如何将嵌套范围元素的引用传递给我的 promise 回调? 有一些最佳实践可以实现这一目标吗? 有什么建议吗?

【问题讨论】:

    标签: javascript angularjs angularjs-scope angular-ui-bootstrap


    【解决方案1】:

    要处理嵌套结构,您可以简单地将容器与字段名称一起传递:

    resolve: {
        container: function () { 
          return thing; // thing would come from edit() parameter
        },
        field: function () {
          return fieldName;
        }
      }
    

    然后从容器而不是范围访问您的数据。这将是穷人的双向绑定。

    --

    另一种方法,在你的指令离开的地方,如下:

    第 1 步)当您使用 ngModel 时,将其添加到指令范围以获得双向绑定:

    scope: {
      ngModel: '='
    },
    

    第2步)将attr参数添加到链接

    link: function (scope, element, attr)
    

    步骤 3) 使字段解析为视图中传递的数据

    resolve: {
      field: function () {
        return attr.external;
      }
    

    步骤 4) 模态完成后将新数据分配给 ngModel

    scope.ngModel = output.selection;
    

    第 5 步)像这样改变你的观点:

    <input type='text' ng-model='thing.value' external="{{thing.label}}"/> Value: {{thing.value}}
    

    小提琴:http://plnkr.co/edit/hj6gOITk0rkHwPqSN9Tf?p=preview

    【讨论】:

    • 您能否以更好的方式详细说明第一个解决方案? “事情将来自edit()参数”是什么意思?一个工作小提琴也很棒!
    【解决方案2】:

    我找到了让它工作的方法:

    我创建了一个指令来直接在元素的 val() 上设置你从 Promise 获得的值。

    .directive("external", function( $modal ){
    
     return {
    
        restrict: "A",
    
        link: function (scope, element) {
    
          element.bind("mousedown", function () {
    
            var modalInstance = $modal.open({
              templateUrl: 'myModalContent.html',
              controller: 'ModalInstanceCtrl',
              resolve: {
                field: function() {
                  return "";
                }
              }
            });
    
            modalInstance.result.then(function( output ) {
              element.val( output.selection );
            }, function() {
              $log.info('Modal dismissed at: ' + new Date());
            });
          });
        }
      };
    });
    

    这样您就可以在事先不知道任何事情的情况下访问您的元素。

    工作演示(link

    【讨论】:

    • 通过 element.val() 更新元素不会反映在您的模型上。
    【解决方案3】:

    如果可能,我建议您考虑所有具有相同结构的数据,这样您就不必处理模态中的条件。

    即使是第一个和第二个:

     $scope.first = {label:'first',value:'initial value'};
     $scope.second = {label:'second ', value:'initial value'};
    

    plunker

    【讨论】:

    • 如果可以的话我会,但在我的情况下这是不可能的
    猜你喜欢
    • 1970-01-01
    • 2014-07-13
    • 1970-01-01
    • 2017-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    相关资源
    最近更新 更多