AngularJS - Atribut nilai pada kotak teks input diabaikan ketika ada model-ng yang digunakan?

218

Menggunakan AngularJS jika saya menetapkan nilai kotak teks input sederhana untuk sesuatu seperti "bob" di bawah ini. Nilai tidak ditampilkan jika ng-modelatribut ditambahkan.

    <input type="text"
           id="rootFolder"
           ng-model="rootFolders"
           disabled="disabled"
           value="Bob"
           size="40"/>

Adakah yang tahu tentang pekerjaan sederhana di sekitar untuk default input ini untuk sesuatu dan menjaga ng-model? Saya mencoba menggunakan ng-binddengan nilai default tetapi tampaknya tidak berhasil juga.

Halo Dunia
sumber

Jawaban:

223

Itu perilaku yang diinginkan, Anda harus mendefinisikan model di controller, bukan di tampilan.

<div ng-controller="Main">
  <input type="text" ng-model="rootFolders">
</div>


function Main($scope) {
  $scope.rootFolders = 'bob';
}
Vojta
sumber
11
Terima kasih. Tetapi dalam kasus ini, model diatur dalam controller. Dan dalam dokumen Angular, selalu sama, data diatur dalam pengontrol. Tapi controller saya ada di file JS. Bagaimana melakukan ketika pada formulir "edit"? Bagaimana cara melewatkan data formulir default ke controller "the angular way"?
ByScripts
8
Ini tidak bekerja untuk saya namun menambahkan atribut tambahan ng-init yang ditunjukkan oleh Mark Rajcok (ng-init = "rootFolders = 'Bob'") berfungsi dengan baik.
Kaizar Laxmidhar
Dan bagaimana cara menetapkan nilai default jika saya memiliki bidang input seperti: <input type = "number" ng-model = "newTransaction [$ index] [user.email]" />?
Shish
188

Vojta mendeskripsikan "Angular way", tetapi jika Anda benar-benar perlu membuat pekerjaan ini, @urbanek baru-baru ini memposting solusi menggunakan ng-init:

<input type="text" ng-model="rootFolders" ng-init="rootFolders='Bob'" value="Bob">

https://groups.google.com/d/msg/angular/Hn3eztNHFXw/wk3HyOl9fhcJ

Mark Rajcok
sumber
33
Anda mungkin tidak memerlukan bagian 'value = "Bob"'.
Mark Rajcok
2
+1 tetapi, Seperti disebutkan dalam salah satu pos pada diskusi tertaut, itu harus dihindari (karena secara logis itu kurang benar & itu membuat pengujian lebih sulit).
0xc0de
1
Metode ini berfungsi dengan baik jika Anda menggunakan nilai model juga pada v1.2. <... ng-init = "rootFolders = someModelAttribute" ...>
dmcqu314
@MarkRajcok, Anda memiliki begitu banyak posting AngularJS di Stack Overflow! Terima kasih untuk semua waktu yang telah Anda curahkan untuk berbagi wawasan Anda dengan komunitas SO. Saya yakin saya berbicara untuk banyak pengembang yang merasa lega ketika saya mengatakan bahwa kami dengan tulus menghargai semua jam Anda telah menyelamatkan kami!
Jeremy Moritz
1
Benar-benar menghargai jawaban Markus yang telah memecahkan masalah saya. Saya mengkonfirmasi bahwa kami TIDAK perlu value="Bob"bagian dalam tag input.
Devner
68

Mengesampingkan arahan input tampaknya melakukan pekerjaan. Saya membuat beberapa perubahan kecil pada kode Dan Hunsaker :

  • Menambahkan tanda centang untuk ngModel sebelum mencoba menggunakan $parse().assign()bidang tanpa atribut ngModel.
  • Mengoreksi urutan assign()fungsi param.
app.directive('input', function ($parse) {
  return {
    restrict: 'E',
    require: '?ngModel',
    link: function (scope, element, attrs) {
      if (attrs.ngModel && attrs.value) {
        $parse(attrs.ngModel).assign(scope, attrs.value);
      }
    }
  };
});
Ivan Breet
sumber
Ini adalah jawaban terbaik yang saya temukan! ... menyelesaikan masalah saya dengan cara yang elegan. Saya harus menangkap nilai pada input tersembunyi (token formulir Symfony, dihasilkan di server).
PachinSV
Ini bukan hanya pintar tetapi solusi terbaik. Dalam kasus saya, saya tidak dapat menetapkan nilai default ng-model pada controller karena merupakan bentuk PHP, jika validasi sisi-server gagal, formulir akan menyegarkan dan apa pun yang ada di ng-model akan hilang menghapus nilai input yang dimasukkan terlalu.
Luis Elizondo
2
Ini tampaknya solusi terbaik jika Anda juga ingin versi dasar formulir HTML Anda berfungsi tanpa JavaScript.
Darren
Solusi luar biasa yang benar-benar harus menjadi opsi yang dapat dikonfigurasi non-standar dalam angular itu sendiri.
Gracie
Terima kasih atas solusinya. Bagaimana Anda memecahkan masalah input nomor? Itu melempar kesalahan docs.angularjs.org/error/ngModel/numfmt?p0=20.12
mate.gwozdz
21

Cara sudut

Cara Angular yang benar untuk melakukan ini adalah dengan menulis aplikasi halaman tunggal, AJAX di Templat formulir, lalu mengisinya secara dinamis dari model. Model tidak diisi dari formulir secara default karena model adalah sumber tunggal kebenaran. Sebaliknya Angular akan pergi ke arah lain dan mencoba untuk mengisi formulir dari model.

Namun, jika Anda tidak punya waktu untuk memulai dari awal

Jika Anda memiliki aplikasi yang ditulis, ini mungkin melibatkan beberapa perubahan arsitektur yang lumayan. Jika Anda mencoba menggunakan Angular untuk meningkatkan formulir yang ada, daripada membangun seluruh aplikasi halaman tunggal dari awal, Anda dapat menarik nilai dari formulir dan menyimpannya dalam ruang lingkup saat tautan menggunakan arahan. Angular kemudian akan mengikat nilai dalam lingkup kembali ke formulir dan menyimpannya dalam sinkronisasi.

Menggunakan arahan

Anda bisa menggunakan arahan yang relatif sederhana untuk menarik nilai dari formulir dan memuatnya ke lingkup saat ini. Di sini saya telah mendefinisikan direktif initFromForm.

var myApp = angular.module("myApp", ['initFromForm']);

angular.module('initFromForm', [])
  .directive("initFromForm", function ($parse) {
    return {
      link: function (scope, element, attrs) {
        var attr = attrs.initFromForm || attrs.ngModel || element.attrs('name'),
        val = attrs.value;
        if (attrs.type === "number") {val = parseInt(val)}
        $parse(attr).assign(scope, val);
      }
    };
  });

Anda dapat melihat saya telah menetapkan beberapa fallback untuk mendapatkan nama model. Anda dapat menggunakan arahan ini bersama dengan arahan ngModel, atau mengikat sesuatu selain $ lingkup jika Anda mau.

Gunakan seperti ini:

<input name="test" ng-model="toaster.test" value="hello" init-from-form />
{{toaster.test}}

Perhatikan ini juga akan berfungsi dengan textareas, dan pilih dropdown.

<textarea name="test" ng-model="toaster.test" init-from-form>hello</textarea>
{{toaster.test}}
superluminary
sumber
Berikut adalah paket modul yang mengimplementasikan solusi yang mirip dengan yang dijelaskan di sini github.com/platanus/angular-keep-values
Agustin
1
Solusi hebat, tetapi hanya akan bekerja dengan input="text". Jika Anda memiliki numberitu akan melempar Model bukan dari tipe number docs.angularjs.org/error/ngModel/numfmt?p0=333
smoksnes
2
Untuk mendukung angka, Anda dapat menambahkan if (attrs.type === "number") val = parseInt(val);
smoksnes
@smoksnes - Anda benar sekali. Saya telah memperbarui jawabannya :)
superluminary
7

Pembaruan: Jawaban asli saya melibatkan pengontrol yang berisi kode DOM-aware, yang memecah konvensi Angular yang mendukung HTML. @dmackerman menyebutkan arahan dalam komentar atas jawaban saya, dan saya benar-benar melewatkannya sampai sekarang. Dengan masukan itu, inilah cara yang tepat untuk melakukan ini tanpa melanggar konvensi Angular atau HTML:


Ada juga cara untuk mendapatkan keduanya - ambil nilai elemen dan gunakan itu untuk memperbarui model dalam arahan:

<div ng-controller="Main">
    <input type="text" id="rootFolder" ng-model="rootFolders" disabled="disabled" value="Bob" size="40" />
</div>

lalu:

app.directive('input', ['$parse', function ($parse) {
    return {
        restrict: 'E',
        require: '?ngModel',
        link: function (scope, element, attrs) {
            if(attrs.value) {
                $parse(attrs.ngModel).assign(scope, attrs.value);
            }
        }
    };
}]);

Anda tentu saja dapat memodifikasi arahan di atas untuk berbuat lebih banyak dengan valueatribut sebelum menetapkan model ke nilainya, termasuk menggunakan $parse(attrs.value, scope)untuk memperlakukanvalue atribut sebagai ekspresi Angular (meskipun saya mungkin akan menggunakan atribut [kustom] yang berbeda untuk itu, secara pribadi, jadi atribut HTML standar secara konsisten diperlakukan sebagai konstanta).

Juga, ada pertanyaan serupa di Pembuatan data yang tersedia untuk model-ng yang mungkin juga menarik.

Dan Hunsaker
sumber
Anda seharusnya tidak melakukan manipulasi / penemuan DOM di controller Anda. Sebaiknya gunakan arahan.
dmackerman
2
Saya secara eksplisit menyebutkan kelemahan itu dalam jawaban saya. Anda seharusnya tidak , tetapi Anda bisa . Itu semua tergantung pada apakah Anda merasa lebih penting untuk mengikuti konvensi Angular atau HTML. Karena Angular memecah HTML.
Dan Hunsaker
3
Oh, saya adalah boneka. Benar-benar melewatkan sedikit tentang menggunakan arahan. Jawaban diperbarui sesuai. Permintaan maaf yang tulus untuk menjadi brengsek bagi Anda, @dmackerman.
Dan Hunsaker
Terima kasih atas arahannya! Itu memberi saya ide untuk diterapkan dalam proyek yang saya kerjakan di mana saya menghasilkan beberapa sisi server konten dan kemudian harus menggunakannya sebagai model saya di klien.
ggalmazor
Senang saya bisa membantu. Tentu saja, secara umum, Anda ingin membangun konten sisi server Anda sebagai JSON dan membuat aplikasi Anda memanipulasi model berdasarkan itu, tetapi kadang-kadang berguna untuk memiliki opsi lain, dan ini hanyalah satu.
Dan Hunsaker
7

Jika Anda menggunakan AngularJs ngModel directive, ingat bahwa nilai valueatribut tidak mengikat pada bidang ngModel . Anda harus init sendiri dan cara terbaik untuk melakukannya, adalah

<input type="text"
       id="rootFolder"
       ng-init="rootFolders = 'Bob'"
       ng-model="rootFolders"
       disabled="disabled"
       value="Bob"
       size="40"/>
Hazarapet Tunanyan
sumber
Rasanya aneh untuk init di direktif / markup alih-alih controller.
random_user_name
5

Ini sedikit modifikasi pada jawaban sebelumnya ...

Tidak perlu $ parse

angular.directive('input', [function () {
  'use strict';

  var directiveDefinitionObject = {
    restrict: 'E',
    require: '?ngModel',
    link: function postLink(scope, iElement, iAttrs, ngModelController) {
      if (iAttrs.value && ngModelController) {
        ngModelController.$setViewValue(iAttrs.value);
      }
    }
  };

  return directiveDefinitionObject;
}]);
dale.lotts
sumber
perlu diingat bahwa ngModelController. $ setViewValue akan mengubah status model menjadi kotor dan murni menjadi false yang juga akan memengaruhi status bentuk yang dapat menyakitkan beberapa saat.
Atul Chaudhary
2

Hai Anda dapat mencoba metode di bawah ini dengan menginisialisasi model.

Di sini Anda dapat menginisialisasi model-ng dari kotak teks dua arah

- Dengan penggunaan ng-init

- Dengan menggunakan $ scope di js

<!doctype html>
 <html >
 <head>
        <title>Angular js initalize with ng-init and scope</title>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
</head>
<body ng-app="app" >
    <h3>Initialize value with ng-init</h3>
    <!-- Initlialize model values with ng-init -->
    <div ng-init="user={fullname:'Bhaskar Bhatt',email:'[email protected]',address:'Ahmedabad'};">
        Name : <input type="text" ng-model="user.fullname" /><br/>
        Email : <input type="text" ng-model="user.email" /><br/>
        Address:<input type="text" ng-model="user.address" /><br/>

    </div>  
    <!-- initialize with js controller scope -->
    <h3>Initialize with js controller</h3>

    <div  ng-controller="alpha">
        Age:<input type="text" name="age" ng-model="user.age" /><br/>
        Experience : <input type="text" name="experience" ng-model="user.exp" /><br/>
        Skills : <input type="text" name="skills" ng-model="user.skills" /><br/>
    </div>  

</body> 
<script type="text/javascript">
        angular.module("app",[])
        .controller("alpha",function($scope){
            $scope.user={};
            $scope.user.age=27;
            $scope.user.exp="4+ years";
            $scope.user.skills="Php,javascript,Jquery,Ajax,Mysql";
        });

     </script>
 </html>                
Bhaskar Bhatt
sumber
0

Masalahnya adalah Anda harus mengatur model ng ke elemen induk ke tempat Anda ingin mengatur nilai-ng / nilai. Seperti yang disebutkan oleh Angular:

Ini terutama digunakan pada input [radio] dan elemen opsi, sehingga ketika elemen dipilih, model ng dari elemen itu (atau elemen induk pilihnya) diatur ke nilai terikat.

Misalnya: Ini adalah kode yang dieksekusi:

<div class="col-xs-12 select-checkbox" >
<label style="width: 18em;" ng-model="vm.settingsObj.MarketPeers">
  <input name="radioClick" type="radio"  ng-click="vm.setPeerGrp('market');" 
         ng-value="vm.settingsObj.MarketPeers" 
         style="position:absolute;margin-left: 9px;">
  <div style="margin-left: 35px;color: #717171e8;border-bottom: 0.5px solid #e2e2e2;padding-bottom: 2%;">Hello World</div>
</label>
</div>

Catatan: Dalam kasus di atas ini saya alreday memiliki respons JSON terhadap model-ng dan nilainya, saya hanya menambahkan properti lain ke objek JS sebagai "MarketPeers". Jadi model dan nilai mungkin tergantung pada kebutuhan, tetapi saya pikir proses ini akan membantu, untuk memiliki kedua-model dan nilai tetapi tidak memiliki mereka pada elemen yang sama.

sg28
sumber
0

Saya memiliki masalah serupa. Saya tidak dapat menggunakan value="something"untuk menampilkan dan mengedit. Saya harus menggunakan perintah di bawah ini di dalam <input>model withe ng saya yang dideklarasikan.

[(ngModel)]=userDataToPass.pinCode

Di mana saya memiliki daftar data dalam objek userDataToPassdan item yang perlu saya tampilkan dan edit adalah pinCode.

Untuk hal yang sama, saya merujuk ke video YouTube ini

tkrloltkr
sumber
Untuk howTo ini, OP menggunakan AngularJS, referensi video YT Anda menggunakan Angular 4.
Chris22