Czy mogę uzyskać dostęp do formularza w kontrolerze?


152

Obecnie używam następujących.

$scope.$$childHead.customerForm[firstName], więc:

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

Ale to działa tylko w Chrome. Teraz spróbowałem następujących rzeczy:

$scope.editCustomerForm[firstName], więc:

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

Co nie działa. Zauważ, że mój formularz znajduje się wewnątrz zakładki Foundation. Jak mogę uzyskać dostęp firstName?

EDYCJA : Wygląda na formto, że nie jest dodawany do karty, scopegdy znajduje się na karcie Podstawy.

Czy ktoś ma na to rozwiązanie?

Odpowiedzi:


210

Chociaż wspomniałem w innych komentarzach, pomyślałem, że przeliteruję to trochę dla tych, którzy używają składni „Kontroler jako”:

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

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

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

</div>

Następnie możesz uzyskać dostęp do FormController w swoim kodzie, na przykład:

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

    function saveChanges() {

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

O ile widzę, szablon nie może wywołać metody "saveChanges", ponieważ nie jest ujawniony w szablonie
— Spock,

2
Metoda „saveChanges” jest ujawniona w trzecim wierszu javascript czy nie rozumiem?
— slopapa

3
to jest dobre, ponieważ oznacza to, że można uniknąć wstrzykiwania całego zakresu, który moim zdaniem jest czystszy
— 72GM

2
Jak to sprawdzić w jaśminie? W mojej specyfikacji vm.myForm jest niezdefiniowany
— bahrieinn

1
Należy to odnotować w oficjalnych dokumentach dla wersji 1.5.X, czyli sposób wykonywania komponentów i es6. dziękuję panu
— MatanCo

91

Możesz dołączyć formularz do obiektu, który jest zdefiniowany w kontrolerze nadrzędnym. Wtedy możesz dotrzeć do swojego formularza nawet z zakresu podrzędnego.

Kontroler rodzica

$scope.forms = {};

Jakiś szablon w zakresie podrzędnym

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

Problem w tym, że formularz nie musi być definiowany w momencie wykonywania kodu w kontrolerze. Więc musisz zrobić coś takiego

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

10
Sugerowałbym użycie var watcher = $scope.$watcheri wewnątrz wyrażenia if, aby wykonać watcher (), aby rozpiąć zegarek. To sprawia, że ​​jest to zegarek jednorazowy, więc nie oglądasz każdego podsumowania po ustawieniu
— willJk

91

Jeśli chcesz przekazać formularz do kontrolera w celu walidacji, możesz po prostu przekazać go jako argument do metody obsługującej przesłanie. Użyj nazwy formularza, więc dla oryginalnego pytania będzie to coś takiego:

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

13
Aby wyjaśnić czytelnikom przyszłych, jeśli mówią, Twój formularz został nazwany / zdefiniowane podobny do tego <form name="myform"></form>, lub nawet <div ng-form name="myform"></div>, wówczas zdarzenie click będzie w następujący sposób: ng-click="submit(myform)". Następnie możesz uzyskać dostęp do obiektu formularza Angular w funkcji klikania, takiej jak: $scope.submit = function (form) { if (form.$valid) {itp.
— Matty J

Tu jest problem - załóżmy, że w formularzu jest lista rozwijana. Użycie powyższej metody daje mi tylko wartość widoku, a nie dokładną wartość, której potrzebuję. A może robię coś złego, dodam skrzypce.
— swateek

82

Trochę za późno na odpowiedź, ale przyszedł z następującą opcją. To działa dla mnie, ale nie jestem pewien, czy jest to właściwy sposób, czy nie.

Moim zdaniem robię to:

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

A w kontrolerze:

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

Teraz po zrobieniu tego mam swój formularz w mojej zmiennej kontrolera, która jest $scope.myForm


1
Jedyne, co do tego dodam, to upewnienie się, że znajduje się na dole formularza.
— smb

Pozycja <div ng-init = "setForm (formName);"> </div> nie ma znaczenia. Tylko uważaj, aby to nie było w formie.
— waqas

1
dobrze, ale wolałbym prostsze rozwiązanie: ng-init = "$ parent.myForm = formName" Bez potrzeby zmiany kontrolera Uwaga: działa tylko z bezpośrednim kontrolerem, w przeciwieństwie do powyższego rozwiązania
— mastilver

Po wypróbowaniu innych metod zdecydowałem się na tę, ponieważ pozwala ona, nameaby atrybut był dokładnie taki, jak chcę. Problem z innymi rozwiązaniami obiektów fikcyjnych polega na tym, że jeśli ten komponent jest używany w innym komponencie z formą ng, to inna forma ng używa tej nazwy formy dosłownie. Więc będzie miało pole z nazwą „dummy.myForm” w postaci literału tekstowego (NIE zagnieżdżonych właściwości), uznałem to za niedopuszczalne.
— Bazylia,

Wielokrotnie próbowałem i nie udało mi się użyć składni controllerAs (pracuję z $ mdDialog). W końcu się na to zgodził i wykonał świetną robotę. Należy tylko pamiętać, że wszelkie inicjalizacje kontrolera muszą być uruchamiane z limitem czasu $, ponieważ formularz nie jest dostępny po pierwszym uruchomieniu kontrolera
— Peter Nixey

22

Aby mieć dostęp do formularza w kontrolerze, musisz dodać go do obiektu fikcyjnego zakresu.

Coś jak $scope.dummy = {}

W Twojej sytuacji oznaczałoby to coś takiego:

<form name="dummy.customerForm">

W swoim kontrolerze będziesz mieć dostęp do formularza poprzez:

$scope.dummy.customerForm

i będziesz mógł robić takie rzeczy

$scope.dummy.customerForm.$setPristine()

WIKI LINK

Mający '.' w modelach zapewni, że w grę wchodzi dziedziczenie prototypowe. Więc użyj <input type="text" ng-model="someObj.prop1">zamiast<input type="text" ng-model="prop1">

Jeśli naprawdę chcesz / potrzebujesz użyć prymitywu, istnieją dwa obejścia:

1. Użyj $ parent.parentScopeProperty w zakresie podrzędnym. Uniemożliwi to zakresowi podrzędnemu utworzenie własnej właściwości. 2. Zdefiniuj funkcję w zakresie nadrzędnym i wywołaj ją od dziecka, przekazując wartość pierwotną do rodzica (nie zawsze jest to możliwe)


Gdzie jest efektywny obszar definiowania wiążącego formularza?
— Gus Crawford,

warto wspomnieć, że dummy.customerFormbędzie niezdefiniowane, dopóki warunki nie ng-ifzostaną spełnione, jeśli element formularza będzie miał na to ng-ifwarunek
— haxxxton

22

Ta odpowiedź jest trochę spóźniona, ale natknąłem się na rozwiązanie, które znacznie ułatwia wszystko.

W rzeczywistości możesz przypisać nazwę formularza bezpośrednio do swojego kontrolera, jeśli używasz składni controllerAs, a następnie odwołać się do niej ze swojej zmiennej „this”. Oto jak zrobiłem to w moim kodzie:

I skonfigurowany kontroler poprzez UI-routera (ale można to zrobić tylko chcesz, nawet w HTML bezpośrednio z czymś takim <div ng-controller="someController as myCtrl">) To co to może wyglądać w konfiguracji routera-ui:

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

a następnie w kodzie HTML po prostu ustaw nazwę formularza jako „kontrolerAs”. „nazwa” w następujący sposób:

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

teraz w kontrolerze możesz to zrobić w bardzo prosty sposób:

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

2
Chociaż jest to w większości ta sama technika, co sugeruje kilka innych odpowiedzi, jest to najlepsza odmiana i powinna być akceptowaną odpowiedzią, zwłaszcza, że ​​wszyscy używają kontrolera Jak i tak teraz.
— Średnik

6

Tak, możesz uzyskać dostęp do formularza w kontrolerze (zgodnie z dokumentacją ).

Z wyjątkiem sytuacji, gdy formularz nie jest zdefiniowany w zakresie kontrolera i zamiast tego jest zdefiniowany w zakresie podrzędnym.

Zasadniczo niektóre dyrektywy kątowe, takie jak ng-if, ng-repeatlub ng-include, utworzą izolowany zakres potomny. Podobnie będzie z wszelkimi dyrektywami niestandardowymi ze scope: {}zdefiniowaną właściwością. Prawdopodobnie na twojej drodze są również komponenty fundamentu.

Miałem ten sam problem podczas wprowadzania prostego ng-ifdookoła <form>tagu.

Zobacz te, aby uzyskać więcej informacji:

Uwaga: sugeruję ponowne napisanie pytania. Odpowiedź na Twoje pytanie brzmi tak, ale Twój problem jest nieco inny:

Czy mogę uzyskać dostęp do formularza w zakresie podrzędnym z poziomu kontrolera?

Na co odpowiedź brzmiałaby po prostu: nie .


... chyba że skonfigurujesz swoje formularze i kontroler zgodnie z opisem w odpowiedzi @ondrs (używając $scope.forms = {}i name="forms.form1")
— marapet

Zobacz odpowiedź bezpośrednio nad twoją przez KhalilRavanna. Dostęp do formularza można uzyskać z poziomu $ scope.formName. Podaje działający przykład
— micahblu

3

dodaj ng-model="$ctrl.formName"atrybut do swojego formularza, a następnie w kontrolerze możesz uzyskać dostęp do formularza jako obiektu wewnątrz kontrolera przezthis.formName


0

Zdecydowanie nie możesz uzyskać dostępu do formularza w zakresie bec. nie jest stworzona. DOM z szablonu html jest ładowany trochę powoli, jak konstruktor kontrolera. rozwiązaniem jest obserwowanie, aż DOM zostanie załadowany i cały zakres zdefiniowany!

w kontrolerze:

$timeout(function(){
    console.log('customerForm:', $scope.customerForm);
    // everything else what you need
});
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.