使用 ng-model 绑定时保留自定义对象类型

Preserving Custom Object Types When Binding Using ng-model

我有一系列扩展基本数组的自定义 javascript 对象。这些对象由数据工厂接收和处理以供主窗体控制器使用。

当绑定到任何输入类型(复选框、单选框、select)时,初始绑定在加载时很好,数据显示并且工作正常。但是,在我更新视图中的值的那一刻,自定义对象类型被覆盖并替换为基本数组。

将数据发送回数据工厂时,我需要知道它是什么类型(有几种),以便确定如何为 SharePoint 列表设置格式。有什么方法可以保留我的对象类型并仍然允许双向绑定吗?

当一个输入通过 ngModel 更新模型时,它通常会用一个覆盖模型初始值的值更新它,并且可能是另一种类型。

有时您可以选择具有内置属性的 return 值,例如复选框或 ng-options 的 ng-true-value 和 ng-false-value "label for value in array"。

如果您不能这样做或需要更可重用的解决方案,您可以使用 ngModel 格式化程序和解析器。

一些背景 - ngModel 实际上包含两个值:

  • $modelValue - 范围 属性 在 ngModel 中使用的实际数据 表达式成立 - 例如在 ng-model="variable" - $modelValue 将是 一个来自变量。
  • $viewValue - 输入控件中使用的值 - 例如,用户看到的文本框中的文本。

通常 $modelValue 和 $viewValue 是相同的,但我们可以选择使用 $formatters 和 $parsers 管道更改它们。

$formatters 是我们可以将函数推送到其中的管道。当$modelValue 变化时(即binded prop 变化),数据将被pipeline 中的函数转换,结果为$viewValue.

$parsers 是相反的管道。每当视图值发生变化时,例如 - 有人将文本输入到输入中,$viewValue 就会使用 $parsers 管道转换为模型值。

底线 - 您可以将自定义对象($modelValue)转换为输入控件($viewValue)中使用的数据,然后再使用这两个管道返回。为此,您创建一个简单的指令,并将您喜欢的任何转换器(函数)添加到管道(数组)中。例如(plunker - 打开控制台并单击复选框):

自定义原型:

  function CustomObj(value) {
    this.value = !!value ? 'cats' : 'dogs';
  }

  CustomObj.prototype.getValue = function getValue() {
    return this.value;
  };

控制器:

    .controller('ExampleController', ['$scope', function($scope) {

      $scope.checkboxModel = {
        value1: new CustomObj(true) // the model is an instance of CustomObj
      };
    }])

管道指令:

    .directive('preserveCustom', function() {
      var ddo = {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, el, attrs, ngModel) {

          function formatter(modelValue) {
            if(modelValue instanceof CustomObj) {
              return modelValue.getValue() === 'cats';
            }

            return value;
          }

          function parser(viewValue) {
            return new CustomObj(viewValue);
          }

          ngModel.$formatters.push(formatter);
          ngModel.$parsers.push(parser);
        }
      }

      return ddo;
    });

和 html:

<input type="checkbox" ng-model="checkboxModel.value1" preserve-custom>