简体   繁体   English

在AngularJS中思考-在AJAX请求中修改DOM的正确方法是什么?

[英]Thinking in AngularJS - what's the proper approach for modifying the DOM in an AJAX request?

I'm brand new to AngularJS. 我是AngularJS的新手。 I've read over "Thinking in AngularJS" if I have a jQuery background? 如果我有jQuery背景,我已经阅读了“ Thinging in AngularJS”? and the answers made a lot of sense. 答案很有道理。 However, I'm still having a hard time translating what I want to do without relying on jQuery. 但是,在不依赖jQuery的情况下,我仍然很难翻译我想做的事情。

My request seems fairly simple. 我的要求似乎很简单。 I have a form that does an AJAX call when submitted. 我有一个提交时会进行AJAX调用的表单。 I want the Submit button to visually update to inform the user on the the AJAX request status. 我希望“提交”按钮以可视方式更新,以通知用户AJAX请求状态。 The Submit button won't be updated with simple text, but instead be updated with text plus a icon. “提交”按钮将不会使用简单的文本进行更新,而是会使用文本和图标进行更新。 The icon is in HTML which means I can't use AngularJS simple data binding. 该图标位于HTML中,这意味着我不能使用AngularJS简单数据绑定。

I have this request working in jsFiddle . 我有这个要求在jsFiddle中工作。

HTML HTML

<div ng-app >
    <form id="id_request" ng-controller="RequestCtrl">
        <input id="id_title" name="title" ng-model="request.title" type="text" class="ng-valid ng-dirty" />
        <button type="submit" class="btn btn-primary" ng-click="submitRequest($event)">
            Submit
        </button>
    </form>
</div>

AngularJS AngularJS

function RequestCtrl($scope, $http) {
    $scope.request = {};
    $scope.submitRequest = function($event) {
        $($event.target).prop("disabled", true).html('<i class="icon-refresh icon-spin"></i> Submitting</a>');
        $http({
            method : 'GET',
            url : '/ravishi/urSDM/3/',
            data : $.param($scope.request),
            headers : {
                'Content-Type' : 'application/x-www-form-urlencoded',
            }
        }).
        success(function(data, status, headers, config) {
            console.log("success");
            console.log($event);
            // This callback will be called asynchronously when the response is available.
            $($event.target).html('<i class="icon-ok"></i> Success').delay(1500).queue(function(next) {
                $(this).removeAttr("disabled").html("Submit");
                next();
            });
        }).
        error(function(data, status, headers, config) {
            console.log("error");
            // Called asynchronously if an error occurs or server returns response with an error status.
            $($event.target).html('<i class="icon-warning-sign"></i> Error').delay(1500).queue(function(next) {
                $(this).removeAttr("disabled").html("Submit");
                next();
            });
        });
    }
}

I am completely aware that this is the wrong way to do it in AngularJS. 我完全意识到这是在AngularJS中执行错误的方法。 I shouldn't be updating the DOM in my controller and I should by trying to avoid jQuery completely. 我不应该在控制器中更新DOM,而应该尝试完全避免使用jQuery。

From what I gather, I need to use directives. 从我的收集中,我需要使用指令。 I've seen some examples but can't think of a nice way to update the button's HTML through the multiple states it goes through. 我已经看到了一些示例,但是想不出一种通过按钮所经历的多个状态来更新按钮的HTML的好方法。 There are four states of the button: 该按钮有四种状态:

1 Initial -> 2 Submitting -> 3 Error or 4 Success -> 1 Initial 1初始-> 2提交-> 3错误或4成功-> 1初始

My first thought is to update an arbitrary button attribute in the controller. 我的第一个想法是更新控制器中的任意按钮属性。 Then in the directive, I would somehow retrieve the attribute value and conditionally update the HTML appropriately. 然后在指令中,我将以某种方式检索属性值并有条件地适当更新HTML。 With this approach, I am still unsure of how to link the status of the AJAX request to the button's HTML in the directive. 使用这种方法,我仍然不确定如何在指令中将AJAX请求的状态链接到按钮的HTML。 Should I forgo the AJAX call in the controller and instead do the AJAX call in the directive by binding to the button's click event? 我应该放弃控制器中的AJAX调用,而是通过绑定到按钮的click事件来在指令中进行AJAX调用吗? Or, is there is a better way to do this? 还是有更好的方法来做到这一点?

The main change you have to do is to move away from manipulating DOM and rather do all changes on the model itself. 您要做的主要更改是远离操纵DOM,而是对模型本身进行所有更改。 Here is an example where I used two separate properties $scope.icon and $scope.locked to control icon style and button state: http://jsfiddle.net/CpZ9T/1/ 这是一个示例,其中我使用了两个单独的属性$scope.icon$scope.locked来控制图标的样式和按钮状态: http : //jsfiddle.net/CpZ9T/1/

In you case, I think you definitely should create a directive to encapsulate the button with its behavior. 在这种情况下,我认为您绝对应该创建一个指令来封装按钮及其行为。 Here's an example: 这是一个例子:

HTML HTML

<div ng-app='app'>
  <form id="id_request" ng-controller="RequestCtrl">
    <input id="id_title" name="title" ng-model="request.title" type="text" class="ng-valid ng-dirty" />
    <my-button state="state" click-fn="submitRequest()"></my-button>
  </form>
</div>

Javascript 使用Javascript

angular.module('app', [])
    .directive('myButton', function() {
    return {
        restrict: 'E',
        scope: { state: '=', clickFn: '&' },
        template: '<button type="submit" class="btn btn-primary" ng-click="clickFn()" ng-disabled="disabled">' +    
                  '  <i ng-class="cssClass"></i>' + 
                  '  {{ text }}' + 
                  '</button>',
        controller: function($scope) {
            $scope.$watch('state', function(newValue) {                                                    
                $scope.disabled = newValue !== 1;
                switch (newValue) {
                    case 1:
                        $scope.text = 'Submit';
                        $scope.cssClass = ''; 
                        break;
                    case 2:
                        $scope.text = 'Submitting';
                        $scope.cssClass = 'icon-refresh icon-spin';  
                        break;
                    case 3:
                        $scope.text = 'Error';
                        $scope.cssClass = 'icon-warning-sign';  
                        break;
                    case 4: 
                        $scope.text = 'Success';
                        $scope.cssClass = 'icon-ok';  
                        break;
                }
            });
        }        
    };
})
.controller('RequestCtrl', function ($scope, $http, $timeout) {
    $scope.state = 1;
    $scope.request = {};

    $scope.submitRequest = function() {
        $scope.state = 2;
        $http({
            method : 'GET',
            url : '/ravishi/urSDM/3/',
            data : $.param($scope.request),
            headers : {
                'Content-Type' : 'application/x-www-form-urlencoded',
            }
        }).
        success(function(data, status, headers, config) {            
            $scope.state = 4;
            $timeout(function() { $scope.state = 1; }, 1500);
            console.log("success");                       
        }).
        error(function(data, status, headers, config) {
            $scope.state = 3;
            $timeout(function() { $scope.state = 1 }, 1500);
            console.log("error");                        
        });
    }
});

jsFiddle here . jsFiddle 在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM