2015-08-13 3 views
0

Так что мой случай использования:AngularJs - Пересвязывание нг-модель

cols = [{field="product.productId"},{field="product.productPrice"}];

data = {products:[{product:{productId:1,productPrice:10}, {product:{productId:2, productPrice:15}}]}

То, что я хотел бы сделать, это:

<div ng-repeat="product in data.products"> 
<div ng-repeat="col in cols"> 
<input type="text" ng-model="product[col.field]"></> 
</div> 
</div> 

Теперь, если col.field был просто «someField», а не «some.deep.field», это сработает. Поскольку поле имеет много элементов, правильным способом сделать ng-модель будет «product [some] [deep] [field]», если я не хочу быть общим и разрешать изменение моих данных и столбцов. Я пробовал этот подход, и он работал для не-общего использования.

То, что я пытался сделать это родовое:

  1. Пересобираем мой элемент 'ввода'. Это создает идеальный HTML E.G, он имеет ng-model = "product ['some'] ['deep'] ['field']" на нем, но никоим образом не связано полем. Возможно, я компилирую с неправильной областью? Я попытался добавитьAttribute ng-init = "hello = 'Hey'" ng-model = "hello" в этот момент, и он работал и правильно привязан ... поэтому я чувствую, что у меня отсутствует что-то относительно области действия здесь.

    compile: function (templateElement) { 
        templateElement[0].removeAttribute('recursive-model'); 
        templateElement[0].removeAttribute('recursive-model-accessor'); 
        return { 
         pre: function (scope, element, attrs) { 
          function convertDotToMultiBracketNotation(dotNote) { 
           var ret = []; 
           var arrayOfDots = dotNote.split('.'); 
           for (i = 0; i < arrayOfDots.length; i++) { 
            ret.push("['" + arrayOfDots[i] + "']"); 
           } 
           return ret.join(''); 
          } 
    
          if (attrs.recursiveModel && attrs.recursiveModelAccessor) { 
           scope[scope.recursiveModel] = scope.ngModel; 
           element[0].setAttribute('ng-model', scope.recursiveModel + convertDotToMultiBracketNotation(scope.recursiveModelAccessor)); 
           var res = $compile(element[0])(scope); 
           console.info('new compiled element:', res); 
           return res; 
          } 
         } 
        } 
    } 
    
  2. Мессинга с NgModelController для форматирования и синтаксического анализа. В этом случае я поместил весь объект «строка» в ng-модель, а затем использовал formatter/parser, чтобы испортить только поле 1, которое меня интересовало. Это работает, пока вы не очистите поле. В этот момент, похоже, полностью уничтожается modelCtrl. $ ModelValue. Других слов - мой console.log говорит:

Настройка поле для VAL 'Текст' на строке [объект]

Настройка поле ВАЛ 'Текс' на строке [объект]

Настройка поля для валь 'Te' на строке [объект]

Установка поле VAL 'T' на строке [объект]

Окружение поле Вала «» на строке [объект]

Настройки поле для VAL «A» на строке неопределенной

link: function (scope, element, attrs, ctrls) { 
     if(ctrls[2] && scope.recursiveModelAccessor){ 
    var modelCtrl = ctrls[2]; 
      modelCtrl.$formatters.push(function (inputValue) { 
       function getValue(object, string){ 
        var explodedString = string.split('.'); 
        for (i = 0, l = explodedString.length; i < l; i++) { 
         object = object[explodedString[i]]; 
        } 
        return object; 
       }; 

       function getValueRecursive (row, field) { 
        if (field instanceof Array) { 
         var ret = []; 
         for (var i = 0; i < col.field.length; i++) { 
          ret.push(getValue(row, field[i])); 
         } 
         return ret.join('/'); 
        } else { 
         return getValue(row, field); 
        } 
       }; 

       return getValueRecursive(modelCtrl.$modelValue, scope.recursiveModelAccessor); 
      }); 
      modelCtrl.$parsers.push(function (inputValue) { 
       function setValueRecursive (row, field, newValue) { 
        if (field instanceof Array) { 
         var firstField = field.shift(); 
         if(field.length==1){ 
          field = field[0]; 
         } 
         setValueRecursive(row[firstField], field, newValue); 
        } else { 
         console.log("Setting "+field+" to val:"+newValue+" on row:"+row); 
         row[field]=newValue; 
        } 
       }; 

       setValueRecursive(modelCtrl.$modelValue, scope.recursiveModelAccessor.split('.'), modelCtrl.$viewValue); 

       return modelCtrl.$modelValue; 
      }); 

ответ

1

длинного рассказ коротких (8 твердых часов тратятся на это) - не ставьте нг -model = «что-то» на вашем объекте, если затем вы планируете повторно компилировать после изменения атрибута ng-model.

рабочая директива для подмены на ngModel (Только не имеет атрибута уже на вашем объекте!)

<div ng-repeat="product in data.products"> 
<div ng-repeat="col in cols"> 
<input type="text" recursive-model="product" recursive-model-accessor="some.deep.field"></input> 
</div> 
</div> 

Просто убедитесь, что вы не имеете нг-модель = «что-то».

Конечно - 100% идеальным решением было бы бросить исключение, если атрибут нг-модель присутствовала :)

module.directive('rebindModel', ['$compile','$parse',function($compile,$parse){ 
return { 
    restrict:'A', 
    compile: function (templateElement) { 
     templateElement[0].removeAttribute('recursive-model'); 
     templateElement[0].removeAttribute('recursive-model-accessor'); 

     return { 
      post: function (scope, element, attrs) { 
       function convertDotToMultiBracketNotation(dotNote) { 
        var ret = []; 
        var arrayOfDots = dotNote.split('.'); 
        for (i = 0; i < arrayOfDots.length; i++) { 
         ret.push("['" + arrayOfDots[i] + "']"); 
        } 
        return ret.join(''); 
       } 

       if (attrs.recursiveModel && attrs.recursiveModelAccessor) { 
        var parsedModelAccessor = $parse(attrs.recursiveModelAccessor) 
        var modelAccessor = parsedModelAccessor(scope); 

        element[0].setAttribute('ng-model', attrs.recursiveModel + convertDotToMultiBracketNotation(modelAccessor)); 
        var res = $compile(element[0])(scope); 
        return res; 
       } 
      } 
     } 
    }, 
} 
}]); 
Смежные вопросы