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 è 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.