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.