template - angularjs docs



Ripristina il modulo allo stato pristine(AngularJS 1.0.x) (5)

Soluzione senza soluzione alternativa

Ho trovato una soluzione che utilizza AngularJS senza alcuna soluzione. Il trucco qui è usare la capacità di AngularJS per avere più di una direttiva con lo stesso nome.

Come altri hanno accennato c'è in realtà una richiesta di pull ( https://github.com/angular/angular.js/pull/1127 ) che è entrato nel ramo 1.1.x di AngularJS che consente il reset dei moduli. Il commit a questa richiesta pull altera le direttive ngModel e form / ngForm (mi sarebbe piaciuto aggiungere un link ma StackOverflow non vuole che aggiunga più di due link).

Ora possiamo definire le nostre direttive ngModel e form / ngForm ed estenderle con la funzionalità fornita nella richiesta pull.

Ho avvolto queste direttive in un modulo AngularJS denominato resettableForm. Tutto quello che devi fare è includere questo modulo nel tuo progetto e la tua versione di AngularJS 1.0.x si comporta come se fosse una versione 1.1.x di Angular a questo proposito.

'' Una volta effettuato l'aggiornamento a 1.1.x non è nemmeno necessario aggiornare il codice, basta rimuovere il modulo e il gioco è fatto! ''

Questo modulo passa anche tutti i test aggiunti al ramo 1.1.x per la funzionalità di reimpostazione del modulo.

Puoi vedere il modulo che funziona in un esempio in un jsFiddle ( http://jsfiddle.net/jupiter/7jwZR/1/ ) che ho creato.

Passaggio 1: includere il modulo resettableform nel progetto

(function(angular) {

// Copied from AngluarJS
function indexOf(array, obj) {
  if (array.indexOf) return array.indexOf(obj);

  for ( var i = 0; i < array.length; i++) {
    if (obj === array[i]) return i;
  }
  return -1;
}

// Copied from AngularJS
function arrayRemove(array, value) {
  var index = indexOf(array, value);
  if (index >=0)
    array.splice(index, 1);
  return value;
}

// Copied from AngularJS
var PRISTINE_CLASS = 'ng-pristine';
var DIRTY_CLASS = 'ng-dirty';

var formDirectiveFactory = function(isNgForm) {
    return function() {
        var formDirective = {
            restrict: 'E',
            require: ['form'],
            compile: function() {
                return {
                    pre: function(scope, element, attrs, ctrls) {
                        var form = ctrls[0];
                        var $addControl = form.$addControl;
                        var $removeControl = form.$removeControl;
                        var controls = [];
                        form.$addControl = function(control) {
                            controls.push(control);
                            $addControl.apply(this, arguments);
                        }
                        form.$removeControl = function(control) {
                            arrayRemove(controls, control);
                            $removeControl.apply(this, arguments);
                        }
                        form.$setPristine = function() {
                            element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
                            form.$dirty = false;
                            form.$pristine = true;
                            angular.forEach(controls, function(control) {
                                control.$setPristine();
                            });
                        }
                    },
                };
            },
        };
        return isNgForm ? angular.extend(angular.copy(formDirective), {restrict: 'EAC'}) : formDirective;
    };
}
var ngFormDirective = formDirectiveFactory(true);
var formDirective = formDirectiveFactory();
angular.module('resettableForm', []).
    directive('ngForm', ngFormDirective).
    directive('form', formDirective).
    directive('ngModel', function() {
        return {
            require: ['ngModel'],
            link: function(scope, element, attrs, ctrls) {
                var control = ctrls[0];
                control.$setPristine = function() {
                    this.$dirty = false;
                    this.$pristine = true;
                    element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
                }
            },
        };
    });
})(angular);

Passaggio 2: fornire un metodo sul controller che reimposta il modello

Si prega di essere consapevole del fatto che è necessario ripristinare il modello quando si reimposta il modulo. Nel tuo controller puoi scrivere:

var myApp = angular.module('myApp', ['resettableForm']);

function MyCtrl($scope) {
    $scope.reset = function() {
        $scope.form.$setPristine();
        $scope.model = '';
    };
}

Passaggio 3: includi questo metodo nel modello HTML

<div ng-app="myApp">
<div ng-controller="MyCtrl">
<form name="form">
    <input name="requiredField" ng-model="model.requiredField" required/> (Required, but no other validators)
    <p ng-show="form.requiredField.$errror.required">Field is required</p>
    <button ng-click="reset()">Reset form</button>
</form>
<p>Pristine: {{form.$pristine}}</p>
</div>
</dvi>

https://ffff65535.com

Una funzione per ripristinare i campi modulo allo stato pristine (ripristino stato sporco) si trova sulla tabella di marcia per AngularJS 1.1.x. Sfortunatamente tale funzione non è presente nell'attuale versione stabile.

Qual è il modo migliore per ripristinare tutti i campi modulo al loro stato originario iniziale per AngularJS 1.0.x.?

Mi piacerebbe sapere se questo è risolvibile con una direttiva o altra soluzione semplice. Preferisco una soluzione senza dover toccare le sorgenti originali di AngularJS. Per chiarire e dimostrare il problema, un link a JSFiddle. http://jsfiddle.net/juurlink/FWGxG/7/

La funzionalità desiderata è nella Roadmap : http://blog.angularjs.org/2012/07/angularjs-10-12-roadmap.html
Richiesta di funzionalità - https://github.com/angular/angular.js/issues/856
Soluzione proposta Pull request - https://github.com/angular/angular.js/pull/1127

Aggiornato con possibile soluzione

Soluzione abbastanza buona?

Ho appena capito che posso ricompilare la parte HTML e rimetterla nel DOM. Funziona e va bene per una soluzione temporanea, ma anche come @blesh menzionato nei commenti:

I controller dovrebbero essere usati solo per la logica di business, non per DOM!

<div id="myform">
  <form class="form-horizontal" name="form">
  </form>
</div>

E nel mio controller su resetForm() :

  • Salva l'originale HTML non toccato
  • Ricompila l'HTML originale salvato
  • Rimuovi il modulo corrente dal DOM
  • Inserisci il nuovo modello compilato nel DOM

Il JavaScript:

var pristineFormTemplate = $('#myform').html();
$scope.resetForm = function () {
    $('#myform').empty().append($compile(pristineFormTemplate)($scope));
}

EDIT ... Sto rimuovendo la mia vecchia risposta, in quanto non era adeguata.

In realtà mi sono imbattuto in questo problema e qui è stata la mia soluzione: ho realizzato un metodo di estensione per angolare. L'ho fatto seguendo un po 'di cosa $ scope.form. $ SetValidity () stava facendo (al contrario) ...

Ecco una demo di plnkr in azione

Ecco il metodo di supporto che ho creato. È un hack, ma funziona:

angular.resetForm = function (scope, formName, defaults) {
    $('form[name=' + formName + '], form[name=' + formName + '] .ng-dirty').removeClass('ng-dirty').addClass('ng-pristine');
    var form = scope[formName];
    form.$dirty = false;
    form.$pristine = true;
    for(var field in form) {
      if(form[field].$pristine === false) {
        form[field].$pristine = true;
      }
      if(form[field].$dirty === true) {
        form[field].$dirty = false;
      }
    }
    for(var d in defaults) {
      scope[d] = defaults[d];
    }
};

Spero che questo sia utile a qualcuno.


Il modo semplice: basta passare il modulo nella funzione controller. Sotto il modulo "myForm" viene fatto riferimento da questo , che è equivalente a $ scope.

<div ng-controller="MyController as mc">
    <ng-form name="myform">
        <input ng-model="mc.myFormValues.name" type="text" required>
        <button ng-click="mc.doSometing(this.myform)" type="submit" 
                ng-disabled="myform.$invalid||myform.$pristine">Do It!</button>
    </ng-form>
</div>

Il controller:

function MyController(MyService) {
    var self = this;
    self.myFormValues = {
        name: 'Chris'
    };
    self.doSomething = function (form) {
        var aform = form;
        MyService.saveSomething(self.myFromValues)
            .then(function (result) {
                ...
                aform.$setPristine();
            }).catch(function (e) {
                ...
            aform.$setDirty();
        })
    }
}

Penso che valga la pena ricordare che nelle versioni successive di Angular (ad esempio 1.1.5), è possibile chiamare $setPristine nel modulo.

$scope.formName.$setPristine(true)

Ciò imposterà anche tutti i controlli del modulo sullo stato originario.

FormController. $ SetPristine


Utilizzando una direttiva esterna e un sacco di jQuery

app.controller('a', function($scope) {
    $scope.caca = function() {
        $scope.$emit('resetForm');
    }
});

app.directive('form', function() {
    return {
        restrict: 'E',
        link: function(scope, iElem) {
            scope.$on('resetForm', function() {
                iElem.find('[ng-model]').andSelf().add('[ng-form]').each(function(i, elem) {
                    var target = $(elem).addClass('ng-pristine').removeClass('ng-dirty');
                    var control = target.controller('ngModel') || target.controller('form');
                    control.$pristine = true;
                    control.$dirty = false;
                });
            });
        }
    };
});

http://jsfiddle.net/pPbzz/2/





angularjs