angularjs 自动保存表单是正确的方法吗? [英] angularjs autosave form is it the right way?

查看:34
本文介绍了angularjs 自动保存表单是正确的方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是在表单有效后自动保存表单并在超时时更新它.我设置如下:

(function(window, angular, undefined) {'使用严格';angular.module('nodblog.api.article', ['restangular']).config(函数(RestangularProvider){RestangularProvider.setBaseUrl('/api');RestangularProvider.setRestangularFields({id:_id"});RestangularProvider.setRequestInterceptor(function(elem, operation, what) {如果(操作 === '放置'){elem._id = 未定义;返回元素;}返回元素;});}).provider('文章', function() {this.$get = function(Restangular) {函数 ngArticle() {};ngArticle.prototype.articles = Restangular.all('articles');ngArticle.prototype.one = function(id) {return Restangular.one('articles', id).get();};ngArticle.prototype.all = function() {返回 this.articles.getList();};ngArticle.prototype.store = 函数(数据){返回 this.articles.post(data);};ngArticle.prototype.copy = 函数(原始){返回 Restangular.copy(original);};返回新的 ngArticle;}})})(窗口,角度);angular.module('nodblog',['nodblog.route']).directive("autosaveForm", function($timeout,Article) {返回 {限制:A",链接:函数(范围、元素、属性){var id = null;scope.$watch('form.$valid', function(validity) {如果(有效性){Article.store(scope.article).then(功能(数据){scope.article = Article.copy(data);_自动保存();},函数错误(原因){抛出新的错误(原因);});}})功能_自动保存(){scope.article.put().then(功能() {$timeout(_autosave, 5000);},函数错误(原因){抛出新的错误(原因);});}}}}).controller('CreateCtrl', function ($scope,$location,Article) {$scope.article = {};$scope.save = function(){if(typeof $scope.article.put === '函数'){$scope.article.put().then(function() {return $location.path('/blog');});}别的{Article.store($scope.article).then(功能(数据){return $location.path('/blog');},函数错误(原因){抛出新的错误(原因);});}};})

我想知道是否有最好的方法.

解决方案

看代码我可以看到,如果当前输入有效并且用户更改了任何有效的内容,$watch 将不会重新触发.这是因为只有在值发生变化时才会执行监视功能.您还应该检查表单的脏状态,并在表单数据持久化后重置它,否则您将陷入无休止的持久循环.

并且您没有清除任何以前的超时.

如果当前超时正在进行,当前代码将保存无效数据.

我已经制定了一个指令来完成这一切并且具有更好的SOC,因此它可以被重复使用.只需为它提供一个回调表达式就可以了.

在这个 plunker 中查看它的实际效果.

演示控制器

myApp.controller('MyController', function($scope) {$scope.form = {状态: {},数据: {}};$scope.saveForm = function() {console.log('保存表单数据...', $scope.form.data);};});

演示 HTML

 

<form name="form.state" auto-save-form="saveForm()"><div><label>仅限数字</label><输入名称=文本"ng-model="form.data.text"ng-pattern="/^\d+$/"/>

<span ng-if="form.state.$dirty &&form.state.$valid">正在更新...</span></表单>

指令

myApp.directive('autoSaveForm', function($timeout) {返回 {要求:['^形式'],链接:函数($scope,$element,$attrs,$ctrls){var $formCtrl = $ctrls[0];var savePromise = null;var 表达式 = $attrs.autoSaveForm ||'真的';$scope.$watch(function() {if($formCtrl.$valid && $formCtrl.$dirty) {如果(保存承诺){$timeout.cancel(savePromise);}savePromise = $timeout(function() {savePromise = null;//还是有效?如果($formCtrl.$valid){if($scope.$eval(expression) !== false) {console.log('表单数据持久化 -- 设置 prestine 标志');$formCtrl.$setPristine();}}}, 500);}});}};});

My goal is to autosave a form after is valid and update it with timeout. I set up like:

(function(window, angular, undefined) {
    'use strict';
    angular.module('nodblog.api.article', ['restangular'])
        .config(function (RestangularProvider) {
            RestangularProvider.setBaseUrl('/api');
            RestangularProvider.setRestangularFields({
                id: "_id"
            });
            RestangularProvider.setRequestInterceptor(function(elem, operation, what) {
                if (operation === 'put') {
                    elem._id = undefined;
                    return elem;
                }
                return elem;
            }); 
        })
        .provider('Article', function() {
            this.$get = function(Restangular) {
                function ngArticle() {};
                ngArticle.prototype.articles = Restangular.all('articles');
                ngArticle.prototype.one = function(id) {
                    return Restangular.one('articles', id).get();
                };
                ngArticle.prototype.all = function() {
                    return this.articles.getList();
                };
                ngArticle.prototype.store = function(data) {
                    return this.articles.post(data);
                };
                ngArticle.prototype.copy = function(original) {
                    return  Restangular.copy(original);
                };
                return new ngArticle;
            }
    })
})(window, angular);

angular.module('nodblog',['nodblog.route'])
.directive("autosaveForm", function($timeout,Article) {
    return {
        restrict: "A",
        link: function (scope, element, attrs) {
            var id = null;
            scope.$watch('form.$valid', function(validity) {
                if(validity){
                    Article.store(scope.article).then(
                        function(data) {
                            scope.article = Article.copy(data);
                            _autosave();
                        }, 
                        function error(reason) {
                            throw new Error(reason);
                        }
                    );
                }  
            })
            function _autosave(){
                    scope.article.put().then(
                    function() {
                        $timeout(_autosave, 5000); 
                    },
                    function error(reason) {
                        throw new Error(reason);
                    }
                );
            }
        }
    }
})

.controller('CreateCtrl', function ($scope,$location,Article) {
        $scope.article = {};
        $scope.save = function(){
            if(typeof $scope.article.put === 'function'){
                $scope.article.put().then(function() {
                    return $location.path('/blog');
                });
            }
            else{
                Article.store($scope.article).then(
                    function(data) {
                        return $location.path('/blog');
                    }, 
                    function error(reason) {
                        throw new Error(reason);
                    }
                );
            }
        };
     })

I'm wondering if there is a best way.

解决方案

Looking at the code I can see is that the $watch will not be re-fired if current input is valid and the user changes anything that is valid too. This is because watch functions are only executed if the value has changed. You should also check the dirty state of the form and reset it when the form data has been persisted otherwise you'll get an endless persist loop.

And your not clearing any previous timeouts.

And the current code will save invalid data if a current timeout is in progress.

I've plunked a directive which does this all and has better SOC so it can be reused. Just provide it a callback expression and you're good to go.

See it in action in this plunker.

Demo Controller

myApp.controller('MyController', function($scope) {

  $scope.form = {
    state: {},
    data: {}
  };

  $scope.saveForm = function() {
    console.log('Saving form data ...', $scope.form.data);  
  };

});

Demo Html

  <div ng-controller="MyController">

    <form name="form.state" auto-save-form="saveForm()">

      <div>
        <label>Numbers only</label>
        <input name="text" 
               ng-model="form.data.text" 
               ng-pattern="/^\d+$/"/>
      </div>

      <span ng-if="form.state.$dirty && form.state.$valid">Updating ...</span>      

    </form>
  </div>

Directive

myApp.directive('autoSaveForm', function($timeout) {

  return {
    require: ['^form'],
    link: function($scope, $element, $attrs, $ctrls) {

      var $formCtrl = $ctrls[0];
      var savePromise = null;
      var expression = $attrs.autoSaveForm || 'true';

      $scope.$watch(function() {

        if($formCtrl.$valid && $formCtrl.$dirty) {

          if(savePromise) {
            $timeout.cancel(savePromise);
          }

          savePromise = $timeout(function() {

            savePromise = null;

            // Still valid?

            if($formCtrl.$valid) {

              if($scope.$eval(expression) !== false) {
                console.log('Form data persisted -- setting prestine flag');
                $formCtrl.$setPristine();  
              }

            }

          }, 500);
        }

      });
    }
  };

});

这篇关于angularjs 自动保存表单是正确的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆