Domanda

Sto cercando di generare un elenco modificabile usando ng-repeat.Voglio ricordare all'utente di aggiornare eventuali modifiche prima di andare avanti, quindi sto usando ng-form per creare moduli "nidificati" al volo perché la documentazione dice che posso quindi utilizzare la convalida su questi input creati dinamicamente.

Mentre sembra funzionare all'interno dell'HTML, non vedo come accedere a quei moduli creati dinamicamente e ai relativi campi di convalida nel controller.In particolare, quando l'utente cambia l'input, uso la proprietà form dirty dirty per far apparire un pulsante per dire all'utente di eseguire il commit delle modifiche.Finora, così buono.Tuttavia, una volta che le modifiche sono state impegnate, voglio $setPristine() sul campo per indicare che le modifiche sono state impostate.Potrebbero esserci altri modi per garantire che le modifiche vengano impegnate su ciascun input prima di consentire il commit del modulo principale, ma questo è stato il meglio che ho potuto trovare.

Sfortunatamente, anche se la documentazione dice che se nomino il ng-form verrà propagato al $scope oggetto, non riesco a trovare un modo per accedervi. $scope.dynamic_form non è definito.

Ecco un plunker che mostra cosa intendo:

plnk

Grazie!

[EDIT] Solo per aggiungere al problema, cosa funziona per questo esempio specifico è aggiungere al ng-click sull'input creato dinamicamente:

ng-click="namesForm.name.$setPristine();clean()"

Ma non ho ancora accesso al modulo creato dinamicamente nel controller.Vorrei, ad esempio, aggiungere un osservatore al namesForm.name.$pristine in modo che io possa impostare il mainForm.$setValidity(false) ogni volta che il sub-form è $dirty per impedire all'utente di inviare il modulo principale fino a quando tutte le modifiche del modulo secondario non sono state eseguite.

Quindi, in poche parole, il problema è come accedere in un controller padre ai valori di convalida di una ngForm nidificata creata dinamicamente?

È stato utile?

Soluzione

Aggiornato 2015-01-17:

Come sottolineato da Leblanc Meneses nei commenti Angolare 1.3 ora supporta l'interpolazione con form, ngForm e input direttiva.

Ciò significa che l'uso di espressioni per nominare i tuoi elementi:

<div ng-form="namesForm_{{$index}}" ng-repeat="name in names">
    <input type="text"
           name="input_{{$index}}_0"></input>
    <!-- ... -->
</div>  

funzionerà come previsto:

$scope['namesForm_0']
$scope.namesForm_1

// Access nested form elements:
$scope.namesForm_1.input_1_0
...

Risposta originale per Angular <= 1.2:

Lavorare con le forme e il ngFormController può diventare difficile abbastanza rapidamente.

È necessario essere consapevoli del fatto che è possibile aggiungere dinamicamente elementi del modulo e input ma non possono essere dinamicamente prende - l'interpolazione non funziona nel ngForm o name direttiva.

Ad esempio, se hai provato a nominare dinamicamente i moduli nidificati in questo modo:

<div ng-form="namesForm_{{$index}}" ng-repeat="name in names">
    <!-- ... -->
</div>  

Invece di rendere disponibili tutti i moduli nidificati nell'ambito in questo modo: scope['namesForm_0'] avresti solo accesso al singolo (ultimo) modulo con il nome letterale scope['namesForm_{{$index}}'].

Nella tua situazione è necessario creare una direttiva personalizzata che verrà aggiunta insieme a ngFormper gestire l'impostazione $pristine$ e $invalid per quell'istanza di forma.

JavaScript:

Questa direttiva vigilerà sulla $dirty stato della sua forma per impostare il $validity per evitare la presentazione quando sporco e gestire l'impostazione del $pristine stato quando viene premuto il pulsante' clean'.

app.directive('formCleaner', function(){
    return {
        scope: true,
        require: '^form',
        link: function(scope, element, attr){
            scope.clean = function () {
                scope.namesForm.$setPristine();
            };

            scope.$watch('namesForm.$dirty', function(isDirty){
                scope.namesForm.$setValidity('name', !isDirty);
            });
        }
    };
});

HTML:

Quindi l'unica modifica al tuo HTML è aggiungere il formCleaner direttiva.

Quindi cambia il tuo HTML originale da questo:

<body ng-controller="MainCtrl">
    <form name="mainForm" submit="submit()">
        <h3>My Editable List</h3>
        <div ng-form="namesForm"
             ng-repeat="name in names">
            <!-- ... -->
        </div>
        <button class="btn btn-default" type="submit">Submit</button>
    </form>
</body>

a questo, aggiungendo form-cleaner accanto ng-form:

<body ng-controller="MainCtrl">
    <form name="mainForm" submit="submit()">
        <h3>My Editable List</h3>

        <!-- Add the `form-cleaner` directive to the element with `ng-form` -->
        <div form-cleaner
             ng-form="namesForm"
             ng-repeat="name in names">
            <!-- ... -->
        </div>
        <button class="btn btn-default" type="submit">Submit</button>
    </form>
</body>

Ecco un Plunker aggiornato che mostra il nuovo comportamento: http://plnkr.co/edit/Lxem5HJXe0UCvslqbJr3?p=preview

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top