2016-03-08 35 views
0

由于对Angular形成验证的方式感到不满,我决定实施我自己的解决方案,并遇到了一个让我难以置信的问题。使用从服务返回的值更新ngModel

我的设置如下:

  1. 一个指令来实例化一个新的形式。
  2. 其控制器访问相关的表单模式,然后通过ng-repeat用于生成视图中的字段。
  3. 这些输入& textarea字段然后通过ng-model绑定到控制器。
  4. 在字段更改或表单提交时,控制器将表单数据发送给验证服务,如果适用,该验证服务返回错误,然后绑定到DOM。

我遇到了一个问题,试图在第4部分验证之前实施卫生步骤。此卫生步骤理论上应使用服务方法的返回值更新控制器数据,更新DOM绑定和允许验证步骤使用更新的值。尽管控制器值本身正在更新,但此更改未反映在DOM中。

相关的代码如下:

检视:

<div ng-repeat="(field, value) in form.schema"> 
    <!-- ... --> 
    <textarea ng-model="form.data[field]" ng-model-options="{ updateOn: 'blur' }" ng-change="form.changed(field)"></textarea> 
    <div class="message">{{ form.errors[field] }}</div> 
</div> 

控制器:

// Controller submit method 
ctrl.submit = function() { 

    var err; 

    for (var field in ctrl.schema) { 
    ctrl.data[field] = validationService.sanitizeField(ctrl.data[field], ctrl.schema[field]); 
    ctrl.errors[field] = validationService.validateField(ctrl.data[field], ctrl.schema[field]); 
    if (ctrl.errors[field] !== undefined) { 
     err = true; 
    } 
    } 

    if (err) { 
    return; 
    } 

    // Proceed ... 

服务:

// Public field sanitation method 
var sanitizeField = function (value, schema) { 
    try { 
    // Try sanitation 
    } 
    catch (e) { 
    // Error 
    } 
    return value; 
} 

记录新ctrl.data[field]值i在卫生条件下,控制器产生正确的结果。这个结果也被正确地传递给后续的validateField方法。但是,新的数据值没有在DOM中更新。

起初,我想这可能是一个问题,没有被应用的范围,或承诺的问题。相应地更新服务&控制器并未解决问题。我也尝试在一个对象中包装卫生回报值,但无济于事。

奇怪的是,将服务中的返回值从value变量更改为原语(例如, 'test',更新返回的DOM。

同样,从服务验证方法返回的错误(也包括字符串而不是变量)在DOM中相应地更新。

尽管有大量的搜索,我还没有找到具体的话题。任何见解都将非常感谢!

回答

1

解决!

Unbeknownst对我,角设有一个ngTrim指令,它被自动绑定到输入域和是默认设置为true [Documentation]。

有了这个指令,数据在控制器提交表单时被自动裁剪 - 由我的卫生服务执行的裁剪因此不会改变数据,这反过来不会反映在DOM中因为Angular没有采取任何改变。

此行为可以通过在视图中的相关字段上设置ng-trim="false"来缓解。

0

尝试做下面的事情;

for (var field in ctrl.schema) { 
    ctrl.data[field] = angular.copy(validationService.sanitizeField(ctrl.data[field], ctrl.schema[field])); 
    ctrl.errors[field] = angular.copy(validationService.validateField(ctrl.data[field], ctrl.schema[field])); 
    if (ctrl.errors[field] !== undefined) { 
     err = true; 
    } 
    } 

当涉及到使用嵌套属性更新对象/数组时,角度是棘手的。您可以使用$scope.$watchCollection来确保对象/数组已更新,或者您可以使用angular.copy(),这将确保DOM更新。

+0

恐怕不行!通过'angular.copy()'运行sanitizeField结果不会改变任何内容,并且指定'ctrl.data [field]'作为可选的目标参数会产生一个'不能复制!来源和目的地是相同的错误:( –