Bisakah saya mengakses formulir di controller?

152

Saat ini saya menggunakan yang berikut ini.

$scope.$$childHead.customerForm[firstName], yang seperti itu:

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

Tetapi ini hanya berfungsi di Chrome. Sekarang saya mencoba yang berikut:

$scope.editCustomerForm[firstName], yang seperti itu:

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

Yang tidak berhasil. Perhatikan formulir saya ada di dalam Tab Yayasan. Bagaimana saya bisa mengakses firstName?

EDIT : Sepertinya formtidak ditambahkan ke scopesaat itu di dalam Tab Yayasan.

Adakah yang punya solusi untuk ini?

Vincent
sumber

Jawaban:

210

Meskipun disinggung dalam komentar lain, saya pikir saya akan sedikit menguraikannya untuk mereka yang menggunakan sintaks "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>

Kemudian Anda dapat mengakses FormController dalam kode Anda seperti:

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

    function saveChanges() {

       if(vm.myForm.$valid) { 
            // Save to db or whatever.
            vm.myForm.$setPristine();
       }
}
slopapa
sumber
Sejauh yang saya lihat, templat tidak dapat memanggil metode "saveChanges", karena tidak terkena templat
Spock
2
Metode "saveChanges" terbuka di baris 3 javascript atau apakah saya salah paham?
slopapa
3
ini bagus karena itu berarti Anda dapat menghindari menyuntikkan seluruh $ lingkup, yang menurut saya lebih bersih
72GM
2
Bagaimana Anda menguji ini dalam melati? Dalam spec saya, vm.myForm tidak terdefinisi
bahrieinn
1
Ini harus dicatat dalam dokumen resmi untuk 1.5.X yang merupakan cara untuk melakukan komponen dan es6. terima kasih pak
MatanCo
91

Anda bisa melampirkan formulir ke beberapa objek yang didefinisikan dalam pengontrol induk. Kemudian Anda dapat mencapai formulir Anda bahkan dari lingkup anak.

Pengontrol induk

$scope.forms = {};

Beberapa templat dalam lingkup anak

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

Masalahnya adalah bahwa formulir tidak harus ditentukan pada saat ketika kode di controller dijalankan. Jadi, Anda harus melakukan sesuatu seperti ini

$scope.$watch('forms.form1', function(form) {
  if(form) {
    // your code...
  }
});
ondrs
sumber
10
Saya sarankan menggunakan var watcher = $scope.$watcherdan di dalam pernyataan if Anda akan mengeluarkan pengamat () untuk melepaskan ikatan arloji. Ini menjadikannya sebagai jam tangan 1 kali sehingga Anda tidak menonton setiap intisari setelah diatur
willJk
91

Jika Anda ingin meneruskan formulir ke controller untuk tujuan validasi, Anda bisa meneruskannya sebagai argumen ke metode yang menangani pengiriman. Gunakan nama formulir, jadi untuk pertanyaan awal itu akan seperti:

<button ng-click="submit(customerForm)">Save</button>
Anthony Shull
sumber
13
Untuk memperjelas bagi pembaca masa depan, jika mengatakan formulir Anda diberi nama / didefinisikan seperti ini <form name="myform"></form>, atau bahkan <div ng-form name="myform"></div>, kemudian acara klik Anda akan menjadi sebagai berikut: ng-click="submit(myform)". Kemudian Anda dapat mengakses objek formulir Sudut dalam fungsi klik Anda seperti: $scope.submit = function (form) { if (form.$valid) {dll.
Matty J
Saya menemukan masalah di sini - katakanlah ada daftar dropdown di formulir. Menggunakan metode di atas hanya memberi saya nilai tampilan dan bukan nilai tepat yang saya butuhkan. Atau saya melakukan sesuatu yang salah, akan menambah biola.
swateek
82

Agak terlambat untuk jawaban tetapi datang dengan opsi berikut. Ini bekerja untuk saya tetapi tidak yakin apakah itu cara yang benar atau tidak.

Dalam pandangan saya, saya melakukan ini:

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

Dan di controller:

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

Sekarang setelah melakukan ini, saya sudah mendapatkan formulir saya di variabel controller saya yang $scope.myForm

Atul Chaudhary
sumber
1
Satu-satunya hal yang saya tambahkan ke ini adalah untuk memastikan ini ada di bagian bawah formulir.
seseorang
Posisi <div ng-init = "setForm (formName);"> </div> tidak masalah. Hanya hati-hati bahwa itu dalam bentuk di bawah.
waqas
1
bagus, tapi saya lebih suka solusi yang lebih sederhana: ng-init = "$ parent.myForm = formName" Tanpa perlu mengubah pengontrol Catatan: ini hanya bekerja dengan pengontrol langsung, berlawanan dengan solusi di atas
mastilver
Setelah mencoba metode lain, saya memutuskan yang ini karena memungkinkan nameatribut untuk menjadi apa yang saya inginkan. Masalah dengan solusi dummy-objek lainnya adalah jika komponen ini digunakan dalam komponen lain dengan bentuk-ng, maka bentuk-ng lain menggunakan nama formulir ini secara harfiah. Jadi itu akan memiliki bidang dengan nama string-literal (BUKAN properti bersarang) dari "dummy.myForm", saya menemukan ini tidak dapat diterima.
Basil
Saya mencoba dan gagal berkali-kali untuk menggunakan sintaks controllerAs (saya bekerja dengan $ mdDialog). Akhirnya setuju untuk ini dan itu berhasil dengan baik. Satu-satunya catatan adalah bahwa setiap inisialisasi pengontrol perlu dijalankan pada $ timeout karena formulir tidak tersedia ketika pengontrol pertama kali berjalan
Peter Nixey
22

Untuk dapat mengakses formulir di controller Anda, Anda harus menambahkannya ke objek lingkup dummy.

Sesuatu seperti $scope.dummy = {}

Untuk situasi Anda, ini berarti:

<form name="dummy.customerForm">

Di controller Anda, Anda akan dapat mengakses formulir dengan:

$scope.dummy.customerForm

dan Anda akan dapat melakukan hal-hal seperti

$scope.dummy.customerForm.$setPristine()

Tautan WIKI

Memiliki sebuah '.' dalam model Anda akan memastikan bahwa warisan prototypal sedang dimainkan. Jadi, gunakan <input type="text" ng-model="someObj.prop1">daripada<input type="text" ng-model="prop1">

Jika Anda benar-benar ingin / perlu menggunakan primitif, ada dua solusi:

1.Gunakan $ parent.parentScopeProperty dalam lingkup anak. Ini akan mencegah ruang lingkup anak dari membuat properti sendiri. 2. Tetapkan fungsi pada lingkup induk, dan panggil dari anak, berikan nilai primitif ke induknya (tidak selalu memungkinkan)

Carsten
sumber
Di mana area efektif untuk mendefinisikan form binding?
Gus Crawford
nilainya menyebutkan bahwa dummy.customerFormakan ditentukan sampai kondisi ng-ifterpenuhi jika elemen bentuk memiliki ng-ifpersyaratan atasnya
haxxxton
22

Jawaban ini agak terlambat, tetapi saya menemukan solusi yang membuat semuanya BANYAK lebih mudah.

Anda benar-benar dapat menetapkan nama formulir langsung ke controller Anda jika Anda menggunakan sintaks controllerAs dan kemudian referensi dari variabel "ini" Anda. Inilah cara saya melakukannya dalam kode saya:

Saya mengkonfigurasi controller melalui ui-router (tetapi Anda dapat melakukannya sesuka Anda, bahkan dalam HTML langsung dengan sesuatu seperti <div ng-controller="someController as myCtrl">) Ini adalah apa yang mungkin terlihat seperti dalam konfigurasi ui-router:

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

dan kemudian di HTML, Anda cukup menetapkan nama formulir sebagai "controllerAs". "name" seperti:

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

sekarang di dalam controller Anda, Anda bisa melakukan ini:

angular
.module("something")
.controller("someController",
    [
       "$scope",
        function ($scope) {
            var vm = this;
            if(vm.someForm.$valid){
              // do something
            }
    }]);
FrankieAvocado
sumber
2
Meskipun ini sebagian besar hanya teknik yang sama seperti beberapa jawaban lain menyarankan, itu variasi terbaik dan harus menjadi jawaban yang diterima, terutama karena semua orang menggunakan controllerAs pula sekarang.
Titik koma
6

Ya, Anda dapat mengakses formulir di controller (seperti yang dinyatakan dalam dokumen ).

Kecuali ketika formulir Anda tidak didefinisikan dalam lingkup pengontrol dan didefinisikan dalam lingkup anak sebagai gantinya.

Pada dasarnya, beberapa arahan sudut, seperti ng-if, ng-repeatatau ng-include, akan menciptakan ruang lingkup anak yang terisolasi. Begitu juga arahan khusus dengan scope: {}properti yang ditentukan. Mungkin, komponen fondasi Anda juga menghalangi Anda.

Saya memiliki masalah yang sama ketika memperkenalkan tag sederhana di ng-ifsekitar <form>.

Lihat ini untuk info lebih lanjut:

Catatan: Saya sarankan Anda menulis ulang pertanyaan Anda. Jawaban untuk pertanyaan Anda adalah ya tetapi masalah Anda sedikit berbeda:

Bisakah saya mengakses formulir dalam lingkup anak dari controller?

Jawabannya sederhana: tidak .

Andre Torgal
sumber
... kecuali jika Anda mengatur formulir dan pengontrol seperti dijelaskan dalam jawaban @ondrs (menggunakan $scope.forms = {}dan name="forms.form1")
marapet
Silakan lihat jawabannya tepat di atas Anda oleh KhalilRavanna. Anda dapat mengakses formulir dari $ scope.formName. Dia memberikan contoh yang berfungsi
micahblu
3

tambahkan ng-model="$ctrl.formName"atribut ke formulir Anda, dan kemudian di controller Anda bisa mengakses form sebagai objek di dalam controller Anda denganthis.formName

Dhurim Kelmendi
sumber
0

Tentunya Anda tidak dapat mengakses formulir dalam lingkup bec. itu tidak dibuat. DOM dari templat html dimuat sedikit lambat seperti konstruktor pengontrol. solusinya adalah menonton sampai DOM dimuat dan semua ruang lingkup ditentukan!

dalam controller:

$timeout(function(){
    console.log('customerForm:', $scope.customerForm);
    // everything else what you need
});
Victor Orletchi
sumber