Posso accedere a un modulo nel controller?


152

Attualmente sto usando il seguente.

$scope.$$childHead.customerForm[firstName], così che:

<form name="customerForm">
  <input type="text" name="firstName" 
         ng-model="data.customer.firstName" 
         tabindex="1"  
         ng-disabled="!data.editable" 
         validationcustomer />
</form>

Ma questo funziona solo in Chrome. Ora ho provato quanto segue:

$scope.editCustomerForm[firstName], così che:

<form name="customerForm" ng-model="editCustomerForm">
  <input type="text" name="firstName" 
         ng-model="data.customer.firstName" tabindex="1"  
         ng-disabled="!data.editable" 
         validationcustomer />
</form>

Che non funziona. Nota che il mio modulo è all'interno di una scheda Fondazione. Come posso accedere firstName?

EDIT : sembra che formnon sia aggiunto a scopequando è all'interno di una scheda Foundation.

Qualcuno ha una soluzione per questo?

Risposte:


210

Anche se accennato in altri commenti, ho pensato di precisarlo un po 'per coloro che usano la sintassi "Controller As":

<div ng-controller="MyController as ctrl">

<form name="ctrl.myForm">
    ...inputs
    Dirty? {{ctrl.myForm.$dirty}}

    <button ng-click="ctrl.saveChanges()">Save</button>
</form>

</div>

Quindi puoi accedere a FormController nel tuo codice come:

function MyController () {
    var vm = this;
    vm.saveChanges = saveChanges;

    function saveChanges() {

       if(vm.myForm.$valid) { 
            // Save to db or whatever.
            vm.myForm.$setPristine();
       }
}

Per quanto posso vedere, il modello non può chiamare il metodo "saveChanges", in quanto non è esposto al modello
— Spock,

2
Il metodo "saveChanges" è esposto nella riga 3 del javascript o sono frainteso?
— slopapa,

3
questo è buono in quanto significa che puoi evitare di iniettare l'intero $ scope, che è più pulito secondo me
— 72GM

2
Come lo testate in gelsomino? Nelle mie specifiche, vm.myForm non è definito
— bahrieinn

1
Questo dovrebbe essere notato nei documenti ufficiali per 1.5.X che è il modo di fare componenti ed es6. grazie signore
— MatanCo,

91

È possibile allegare il modulo a un oggetto definito in un controller principale. Quindi puoi raggiungere il tuo modulo anche da un ambito figlio.

Controllore principale

$scope.forms = {};

Alcuni template in un ambito figlio

<form name="forms.form1">
</form>

Il problema è che il modulo non deve essere definito nel momento in cui viene eseguito il codice nel controller. Quindi devi fare qualcosa del genere

$scope.$watch('forms.form1', function(form) {
  if(form) {
    // your code...
  }
});

10
Suggerirei di usare var watcher = $scope.$watchere all'interno dell'istruzione if dovresti eccitare watcher () per separare l'orologio. Questo lo rende un orologio 1 volta in modo da non guardare tutti i digest dopo che è stato impostato
— sarà il

91

Se si desidera passare il modulo al controller a fini di convalida, è possibile passarlo semplicemente come argomento al metodo che gestisce l'invio. Usa il nome del modulo, quindi per la domanda originale sarebbe qualcosa del tipo:

<button ng-click="submit(customerForm)">Save</button>

13
Per chiarire per i lettori futuri, se dire la vostra forma è chiamato / definito simile a questo <form name="myform"></form>, o anche <div ng-form name="myform"></div>, allora il vostro evento click sarebbe la seguente: ng-click="submit(myform)". Quindi puoi accedere all'oggetto forma angolare nella tua funzione clic come: $scope.submit = function (form) { if (form.$valid) {ecc.
— Matty J

Trovo un problema qui - diciamo che c'è un elenco a discesa nel modulo. L'uso del metodo sopra mi dà solo il valore della vista e non il valore esatto di cui ho bisogno. O sto facendo qualcosa di sbagliato, aggiungerò un violino.
— Swateek,

82

Un po 'in ritardo per una risposta, ma è venuto con la seguente opzione. Funziona per me, ma non sono sicuro che sia il modo corretto o meno.

Dal mio punto di vista lo sto facendo:

<form name="formName">
    <div ng-init="setForm(formName);"></div>
</form>

E nel controller:

$scope.setForm = function (form) {
    $scope.myForm = form;
}

Ora dopo aver fatto questo ho ottenuto il mio modulo nella mia variabile controller che è $scope.myForm


1
L'unica cosa che aggiungerei a questo è assicurarmi che sia in fondo al modulo.
— smb,

La posizione di <div ng-init = "setForm (formName);"> </div> non ha importanza. Basta fare attenzione che sotto forma.
— Waqas,

1
bene, ma preferirei una soluzione più semplice: ng-init = "$ parent.myForm = formName" Senza la necessità di cambiare il controller Nota: funziona solo con il controller diretto, contrariamente alla soluzione sopra
— mastilver

Dopo aver provato gli altri metodi, ho optato per questo perché permette nameall'attributo di essere esattamente quello che voglio che sia. Il problema con le altre soluzioni dummy-object è se questo componente viene utilizzato in un altro componente con un ng-form, che l'altro ng-form usa letteralmente questo nome di moduli. Quindi avrà un campo con un nome letterale stringa (proprietà NON nidificate) di "dummy.myForm", l'ho trovato inaccettabile.
— Basilio,

Ho provato e fallito molte volte ad usare la sintassi controllerAs (sto lavorando con $ mdDialog). Finalmente risolto per questo e ha fatto un ottimo lavoro. L'unica nota è che qualsiasi inizializzazione del controller deve essere eseguita su un timeout $ poiché il modulo non è disponibile quando il controller viene eseguito per la prima volta
— Peter Nixey,

22

Per poter accedere al modulo nel controller, è necessario aggiungerlo a un oggetto scope fittizio.

Qualcosa di simile a $scope.dummy = {}

Per la tua situazione questo significherebbe qualcosa di simile:

<form name="dummy.customerForm">

Nel tuo controller potrai accedere al modulo:

$scope.dummy.customerForm

e sarai in grado di fare cose come

$scope.dummy.customerForm.$setPristine()

WIKI LINK

Avere un '.' nei tuoi modelli assicurerà che l'ereditarietà prototipale sia in gioco. Quindi, usa <input type="text" ng-model="someObj.prop1">piuttosto che<input type="text" ng-model="prop1">

Se vuoi davvero / hai bisogno di usare una primitiva, ci sono due soluzioni alternative:

1.Utilizzare $ parent.parentScopeProperty nell'ambito secondario. Ciò impedirà all'ambito figlio di creare la propria proprietà. 2. Definire una funzione sull'ambito padre e chiamarla dal figlio, passando il valore primitivo al padre (non sempre possibile)


Dov'è l'area effettiva per definire il modulo vincolante?
— Gus Crawford,

vale la pena ricordare che dummy.customerFormrimarrà indefinito fino a quando le condizioni di non ng-ifsaranno soddisfatte se l'elemento di forma ne ha una ng-ifcondizione
— haxxxton

22

Questa risposta è un po 'in ritardo, ma mi sono imbattuto in una soluzione che rende MOLTO più facile.

Puoi effettivamente assegnare il nome del modulo direttamente al tuo controller se stai usando la sintassi controllerAs e quindi fare riferimento a esso dalla tua variabile "this". Ecco come l'ho fatto nel mio codice:

Ho configurato il controller tramite ui-router (ma puoi farlo come vuoi, anche in HTML direttamente con qualcosa del genere <div ng-controller="someController as myCtrl">) Ecco come potrebbe apparire in una configurazione di ui-router:

views: {
            "": {
                templateUrl: "someTemplate.html",
                controller: "someController",
                controllerAs: "myCtrl"
            }
       }

e poi nell'HTML, basta impostare il nome del modulo come "controllerAs". "name" in questo modo:

<ng-form name="myCtrl.someForm">
    <!-- example form code here -->
    <input name="firstName" ng-model="myCtrl.user.firstName" required>
</ng-form>

ora all'interno del tuo controller puoi semplicemente farlo:

angular
.module("something")
.controller("someController",
    [
       "$scope",
        function ($scope) {
            var vm = this;
            if(vm.someForm.$valid){
              // do something
            }
    }]);

2
Sebbene questa sia principalmente la stessa tecnica suggerita da molte altre risposte, è la variante migliore e dovrebbe essere la risposta accettata, soprattutto dal momento che tutti usano controllerAs adesso.
— Punto

6

Sì, puoi accedere a un modulo nel controller (come indicato nei documenti ).

Tranne quando il modulo non è definito nell'ambito del controller e viene invece definito in un ambito figlio.

Fondamentalmente, alcune direttive angolari, come ng-if, ng-repeato ng-include, creeranno un ambito figlio isolato. Così sarà qualsiasi direttiva personalizzata con una scope: {}proprietà definita. Probabilmente, anche i componenti della tua fondazione sono sulla tua strada.

Ho avuto lo stesso problema quando ho introdotto un semplice ng-ifattorno al <form>tag.

Vedi questi per maggiori informazioni:

Nota: ti suggerisco di riscrivere la tua domanda. La risposta alla tua domanda è sì ma il tuo problema è leggermente diverso:

Posso accedere a un modulo in un ambito figlio dal controller?

A cui la risposta sarebbe semplicemente: no .


... a meno che non imposti i moduli e il controller come descritto nella risposta di @ondrs (utilizzando $scope.forms = {}e name="forms.form1")
— marapet,

Si prega di vedere la risposta immediatamente sopra la tua di KhalilRavanna. Puoi accedere al modulo da $ scope.formName. Fornisce un esempio funzionante
— micahblu,

3

aggiungi l' ng-model="$ctrl.formName"attributo al tuo modulo e quindi nel controller puoi accedere al modulo come oggetto all'interno del tuo controller dathis.formName


0

Sicuramente non è possibile accedere al modulo nell'ambito. non è stato creato. Il modello DOM da html viene caricato un po 'lentamente come il costruttore del controller. la soluzione è guardare fino a quando non viene caricato DOM e tutto l'ambito definito!

nel controller:

$timeout(function(){
    console.log('customerForm:', $scope.customerForm);
    // everything else what you need
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.