处理开机自检后从 Angular 控制器到指令的成功/错误 DOM 操作

Handling success/error DOM manipulation from Angular controller to directive after POST

本文关键字:成功 错误 操作 DOM 指令 开机自检 Angular 控制器 处理      更新时间:2023-09-26

我一直在这里和那里学习角度,但我不太明白处理来自服务器的成功/错误响应的角度方式是什么。典型的jQuery方法是:

  • 序列化表单中的数据
  • $.发布数据到服务器
  • 服务器验证数据,响应成功或错误数据
  • 使用 jQuery 来操作 DOM 以显示来自服务器的成功/错误数据。

在 angular 中,我们有操作 DOM 的指令,我们有处理模型的控制器。假设我们有以下内容:

形式.html

<div ng-controller="myController">
    <span class="hidden success-message"></span>
    <form>
        <label> Name </label>
        <input type="text" name="name" ng-model="name">
        <span class="name-error hidden"></span>
        <label> Occupation </label>
        <input type="text" name="occupation" ng-model="occupation">
        <span class="occupation-error hidden"></span>
        <input submit-directive type="submit" id="submit" value="Submit">
    </form>
</div>

应用.js

angular.module('app', []).controller('myController', [$scope, $http, function($scope, $http) {
    $scope.name = "";
    $scope.occupation = "";
    $scope.doSubmit: function(formData) {
        $http.post("/save", formData)
        .success(function(response) {
            $scope.name = response['name']
            $scope.occupation = response['occupation']
            // How to pass success messages back to directive?
        }.fail(function(err) {
            // How to pass error messages back to directive?
        }
    }
});
angular.module('app', []).directive('submit-directive', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
             element.click(function() {
                 // Pass form data back to controller
                 scope.$apply('doSubmit('"' + $("form").serialize() +''")');
             });
             // How do I get the success/fail results from the Controller so that I can manipulate the DOM?
        }
    };
});

在这里,用户输入他们的nameoccupation。提交后,指令将获取表单数据并将其呈现给控制器以进行 POST 请求。返回响应时,指令应显示成功消息或显示错误消息。

目前尚不清楚如何将响应从控制器传递到 DOM 操作指令。

我想到的唯一方法是创建一个$watch

// in controller
$scope.isFormPostSuccess = false;
$scope.formResponse = null;
// ....
.success(function(response) {
     $scope.isFormPostSuccess = true;
     $scope.formResponse = response;
}.fail(function(err) {
     $scope.isFormPostSuccess = false;
     $scope.formResponse = err;
}

然后在指令中,我会观察这些变量的变化并采取相应的行动。但是,这种方式感觉非常混乱,并且对于较大的应用程序或具有许多独立表单时似乎不能很好地扩展。我也可以将所有 DOM 操作移动到控制器中,但这只是糟糕的设计。

什么是正确的角度方式?

实际上,所谓的"角度方式"应该是将模型($scope.foo)的使用与指令(如ng-modelng-bindng-show等,或你的自定义指令)相结合,以实现DOM操作的目标。这不像在控制器中手动启动 DOM 操作,而是在控制器中更改模型,DOM 将在指令的帮助下相应地更新自身。

在您的情况下,如果您只想显示成功/错误消息,我认为您不需要使用自定义指令。


首先,您应该将相关表单字段包装在单个模态对象中,而不是多个模态对象中。喜欢:

<input type="text" name="name" ng-model="person.name">

<input type="text" name="occupation" ng-model="person.occupation">

其次,您应该使用ng-submitng-click进行表单提交操作,例如:

<input type="submit" id="submit" value="Submit" ng-click="doSubmit(person)">

<form ng-submit="doSubmit(person)">
    ...
    <input type="submit" id="submit" value="Submit">
</form>

第三,您应该使用ng-model将数据从表单中取出,而不是serialize()。如如何将数据发布为表单数据而不是请求有效负载中所述?:

$scope.doSubmit = function(formData) {    // use `=` instead of `:` here
    $http({
        method: "POST",
        url: "/save",
        data: $.param(formData),
        headers: {'Content-Type': 'application/x-www-form-urlencoded'}
    })
    // ...
}

最后,如果你想向用户显示一些文本以外的反馈,你应该尽可能使用 ng-showng-switchng-classng-style。喜欢:

<span class="name-error" ng-show="errorMessage.name" ng-bind="errorMessage.name"></span>

fail()回调中,当您要显示名称错误消息时:

errorMessage.name = "Some error message here.";  // don't forget to initialize errorMessage to an empty object

就是这样!


更新

对于您在评论中提出的问题,我认为,在 Angular 中,人们可能更喜欢对单个 DOM 元素或嵌套指令使用单独的内聚指令,然后将它们与模型或控制器(嵌套指令)连接起来。

在您的示例中,我建议您同时使用两者的组合。

首先,将一组嵌套指令用于 UI 目的。您可能有一个绑定到 body 标记并访问其中的视口信息的指令。然后,您可以使用 require: '^ParentDirective' 在内部指令中访问它。

然后,可以将模型绑定到 inside 指令。因此,您将数据和 UI 操作分开。

例如

<body auto-size-messages>
    <div ng-repeat="message in messages" message="message"></div>
</body>

auto-size-messages 中,您可以获取视口属性并将其分配给控制器。在message中,您可以操纵 DOM 将消息放置在您想要的位置并根据消息属性显示内容。

对于嵌套指令,您可以参考 https://docs.angularjs.org/guide/directive 中的创建包装其他元素的指令部分。