javascript - dirty - angularjs form data validation



Come accedere a FormController nel controller principale o nell'ambito in AngularJS (7)

Ho una pagina con più moduli e voglio mostrarne solo uno alla volta. Per questo ho separato ogni modulo in una sezione e utilizzando il plugin per fisarmonica di Bootstrap ho solo permesso una sezione aperta alla volta.

Il mio markup assomiglia a questo:

<a ng-click="open_section('section1')">Section 1</a>

<div collapse="section1">
  <form name="section1Form">
  </form>
</div>

<a ng-click="open_section('section2')">Section 2</a>

<div collapse="section2">
  <form name="section2Form">
  </form>
</div>

Tutto funziona bene, posso navigare tra le forme, ecc.

Poiché non desidero che l'utente apra una sezione se quella che stanno attualmente modificando contiene errori di convalida, ho provato a verificare nella funzione open_section se il modulo ad esso associato è valido o meno.

Ci ho provato, ma non ho potuto. Non ho potuto accedere al FormController associato ai moduli nel controller che è responsabile della pagina. Per qualche ragione, non vengono pubblicati sullo scope.

Questo è quello che ho provato:

  • $scope.section1Form undefined è undefined

  • provato con $scope.$watch('section1Form, function(){}) , ancora non definito

  • open_section provato ad aggiungere il nome del form come secondo parametro a open_section modo: open_section('section1', section1Form) ma nella funzione il secondo argomento undefined è undefined .

Tra i <form></form> , ho accesso a FormController, ma al di fuori di essi non lo faccio. Poiché l'evento proviene da <form> (la chiusura, l'apertura delle sezioni) non posso passare il FormController al mio controller per verificare la validità dei miei moduli.

C'è un modo per aggirare questo, o dovrei refactoring la mia pagina?

Sto usando Angular 1.1.5 BTW.

Inoltre, verificando con il plug-in AngularJS Batarang Chrome, posso vedere che i moduli vengono pubblicati come ambiti figlio nell'ambito corrente.

EDIT : questo è il modo in cui la gerarchia dell'ambito cerca questa app

 - root
 |
 ---current controller\'s scope
 |
 ----scope that contains the forms

È perché sto usando ng-include ? Non c'è modo di accedere a quei moduli in un controller allora?

https://ffff65535.com


Il tuo controller potrebbe essere al di fuori del tuo modulo O stai cercando di ottenere il tuo modulo prima che il modulo venga popolato nello scope.

Ho creato un PlunkR e funziona bene.


Nella documentazione angolare si può leggere:

<form
       [name="{string}"]>
</form>

Nome del modulo Se specificato, il controller del modulo verrà pubblicato nell'ambito correlato, sotto questo nome.

Tuttavia, esistono alcune direttive, come ngIf , che creano un nuovo ambito:

Si noti che quando un elemento viene rimosso usando ngIf il suo ambito viene distrutto e viene creato un nuovo ambito quando l'elemento viene ripristinato.

Può essere il tuo caso? In tal caso, puoi provare a impostare il nome del modulo su qualcosa come "forms.section1Form" e quindi accedervi di conseguenza nell'ambito.


Esiste un modo molto più semplice per comunicare di nuovo nella gerarchia dell'ambito usando il processo angolare di ricerca di oggetti nella sua gerarchia di scope.

Ciò ci consente di collegare l'oggetto da un ambito inferiore a un ambito più elevato utilizzando la notazione dot.

In questo caso è necessario creare un oggetto vuoto "catcher" sul controller di primo livello. A questo oggetto catcher possono quindi essere assegnati gli oggetti modulo dagli ambiti inferiori. Ecco un plunk per la demo.

http://plnkr.co/edit/xwsu48bjM3LofAoaRDsN?p=preview

Non è perfettamente elegante, ma se pensi a questo oggetto "catcher" come un ascoltatore di eventi, stiamo ancora seguendo uno schema standard.

crea un oggetto catcher vuoto nel controller in cui desideri un riferimento al modulo nidificato

function mainController($scope){
  $scope.catcher = {

  };
 }

Quindi nel markup stesso ogni volta che viene dichiarata la direttiva ng-form, imposta catcher.formName = formName in questo modo

<ng-form name="alpha">
          <span ng-init="catcher.alpha = alpha"></span>
          <input type="text" required="" ng-model="alphaValue" />
        </ng-form>

Poiché siamo assegnati a "catcher.", L'angolare attraverserà la gerarchia dell'ambito e la troverà nel mainController indipendentemente da qualsiasi numero di controller nel mezzo (supponendo che anche loro non abbiano un oggetto catcher, ovviamente)


Per gestire i moduli dinamici e quindi la posizione dinamica del associato FormController, ho utilizzato una semplice direttiva per individuare l'ambito che contiene il modulo.

Soluzione:

Crea una direttiva che $ emetta sia l'ambito associato con il modulo:

  module.directive('formLocator', function() {
    return {
      link: function(scope) {
        scope.$emit('formLocator');
      }
    }

Usa la direttiva nel markup:

<form name="myForm" novalidate form-locator>

Ascolta l'evento trasmesso dalla direttiva nel tuo controller:

$scope.$on('formLocator', function(event) {
  $scope.myDeeplyNestedForm = event.targetScope.myForm;
});

So che questo causerà un sacco di orrore .... ma ero piuttosto pigro e ho usato il seguente (che mi piacerebbe credere che non crei un sovraccarico dovuto all'aggiunta come orologio e ad eseguire ogni digest):

<form name = "formName" nf-if="someCondition">

{{(controller.referenceToForm==undefined && (controller.referenceToForm=formName) != undefined)?'':''}}

</form>

Quindi uso solo controller.referenceToForm all'interno del mio controller, ecc.


Simile alla soluzione Sunil D., sono arrivato a uno simile, ma impostando implicitamente la variabile scope, il formController in cui è stato utilizzato il tag, in quanto non volevo codificare il nome del modulo due volte:

renderFormModule.directive('formLocator', function() {
    return {
        link: function(scope, element) {
            scope.formAssociated = scope[element[0].name];
        }
    }
});

E poi, la vista qualcosa di simile:

    <form name="testForm" ng-controller='formController as formCtrl' form-locator novalidate>

Per quanto riguarda la nuova soluzione di Sunil D. per fornire l'ambito del modulo agli ambiti padre (consultare https://.com/a/22487840/1518575 ), è possibile ottenere effettivamente l'ambito del modulo dall'oggetto evento inviato in $ emettere una chiamata

Almeno dall'Angular 1.0.3, l'oggetto evento ha una proprietà targetScope, che fa riferimento all'ambito su cui l'evento era $ emit-ed. (Vedi http://docs.angularjs.org/api/ng/type/ $ rootScope.Scope # $ on per ulteriori informazioni sulle proprietà dell'oggetto evento.)

Con questo in mente, è possibile semplificare il codice della direttiva di Sunil D. come:

module.directive('formLocator', function() {
  return {
    link: function(scope) {
      scope.$emit('formLocator');
    }
  };
});

Il modello non cambia affatto:

<form name="myForm" novalidate="" form-locator>

E successivamente cambieresti il ​​codice di gestione degli eventi per essere:

$scope.$on('formLocator', function(event) {
  $scope.myDeeplyNestedForm = event.targetScope.myForm;
});

Questa direttiva sarebbe rilevante in ogni scenario in cui si desidera fornire un ambito a uno dei suoi antenati, non solo nel caso di ngForm. Nella mia base di codice, ho rinominato questa direttiva al "presente" più generico, dal momento che un modo per pensare allo scopo della direttiva è che annuncia la presenza di un ambito.





angularjs-scope