控制器中设置的表单值在页面焦点之前不会更新

时间:2017-02-06 11:04:12

标签: angularjs

这是我表格的一部分:

<form name="form.activityForm" class="form-horizontal" ng-submit="save(form.activityForm.$valid)"
          enctype="multipart/form-data" novalidate>
    <fieldset>
        <div class="form-group" ng-if="!activity._id">
            <label for="gpxData" ng-class="{ 'disabled': gpxFileName }" class="btn btn-primary btn-file">Upload GPX
                <input type="file" nv-file-select name="gpxData" id="gpxData" ng-model="gpxData" uploader="uploader"
                           onchange="angular.element(this).scope().setFileName()" hidden>
            </label>
            <span ng-if="gpxFileName" ng-bind="gpxFileName"></span>
        </div>

        <div class="form-group" show-errors>
            <label class="control-label" for="name">Name</label>
            <input name="name" type="text" ng-model="activity.name" id="name" class="form-control"
                       ng-disabled="!gpxFileName" required>
            <div role="alert" class="alert alert-danger" ng-if="(activity.name === 'N/A') && (gpxFileName)">
                <p>This activity does not have a <strong>name</strong>. Please select one.</p>
            </div>
            <div ng-messages="form.activityForm.name.$error" role="alert">
                <p class="help-block error-text" ng-message="required">Activity name is required.</p>
            </div>
        </div>

        ...
    </fieldset>
</form>

setFileName()

$scope.setFileName = () => {
    let fr = new FileReader(),
        gpxFile = document.getElementById("gpxData").files[0],
        filename = gpxFile.name;

    fr.onload = () => {
        let gpxDataXml = parseXmlFromString(fr.result);

        setNameTypeDescription(gpxDataXml.documentElement);
    };
    fr.readAsText(gpxFile);
    $scope.gpxFileName = filename;
};

setNameTypeDescription()

let setNameTypeDescription = (gpxDataXmlDocumentElement) => {
    let activityType = getSingleTagData(gpxDataXmlDocumentElement, "type");

    $scope.activity.name = getSingleTagData(gpxDataXmlDocumentElement, "name");
    $scope.activity.description = getSingleTagData(gpxDataXmlDocumentElement, "descr");

    $scope.activityTypes.forEach((type) => {
        if (type.name.toLowerCase() === activityType.toLowerCase()) {
            $scope.activity.type = type;
        }
    });
};

当我在控制器中更改了值(即$scope.activity.name)后,我得到了预期的输出。但是,模板中的值(即ng-model="activity.name")在页面上再次聚焦(即单击按钮)之前不会更新

修改

要添加,我需要使用ng-model,因为我需要双向绑定。尽管该值最初是在控制器中设置的,但用户也可以更改模板中的值,并在表单提交时将该值保存到mongo中。

此外,ng-bind在此方案中无效。

2 个答案:

答案 0 :(得分:4)

您的问题是,您正在更新绑定到视图的值,但有角度不知道&#34;知道&#34;他们是更新。 Angular更新每个摘要周期的视图,这种情况会发生很多次 - 当用户与视图交互时,或者在角度能够跟踪的范围发生任何变化之后。

在你的情况下,你在文件更改后调用self.wfile.write(output.encode()) (在文件输入上使用setNameTypeDescription事件。由于onchange不是原生角度指令,你必须让角知道手动改变了一些东西。

它再次集中在页面上时起作用,因为它触发了一个更新视图的摘要周期,但你可以从控制器那样做:

onchange

当然 - 别忘了向控制器注入$timeout(function() { $scope.activity.name = getSingleTagData(gpxDataXmlDocumentElement, "name"); // You can also put here other view related changes, you don't need a separate $timeout for every change });

请注意,您也可以使用$timeout包装代码,但$scope.$apply(function() { ... });已经为您执行此操作,我更喜欢$timeout,因为您不会遇到像 $ {摘要} {$ 3}}中解释了$ scope。$ apply()正在进行$ digest。

答案 1 :(得分:0)

尝试使用ng-bind而不是ng-model