AngularJS - แอ็ตทริบิวต์ค่าบนกล่องข้อความอินพุตจะถูกละเว้นเมื่อใช้ ng-model หรือไม่?


219

การใช้ AngularJS ถ้าฉันตั้งค่ากล่องข้อความแบบง่าย ๆ ให้เป็นแบบ "bob" ด้านล่าง ค่าจะไม่แสดงหากng-modelมีการเพิ่มคุณสมบัติ

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

ใครรู้วิธีง่ายๆในการเริ่มต้นการป้อนข้อมูลนี้เพื่ออะไรและเก็บng-model? ฉันพยายามใช้ng-bindกับค่าเริ่มต้น แต่ดูเหมือนจะไม่ทำงานเช่นกัน

คำตอบ:


223

นั่นเป็นพฤติกรรมที่ต้องการคุณควรกำหนดรูปแบบในคอนโทรลเลอร์ไม่ใช่ในมุมมอง

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


function Main($scope) {
  $scope.rootFolders = 'bob';
}

11
ขอบคุณ แต่ในกรณีนี้รุ่นถูกตั้งค่าในคอนโทรลเลอร์ และในเอกสารเชิงมุมก็เหมือนกันทุกครั้งที่มีการตั้งค่าข้อมูลในคอนโทรลเลอร์ แต่ตัวควบคุมของฉันอยู่ในไฟล์ JS ทำอย่างไรเมื่ออยู่ในรูปแบบ "แก้ไข"? จะส่งข้อมูลฟอร์มเริ่มต้นไปยังตัวควบคุม "วิธีเชิงมุม" ได้อย่างไร
ByScripts

8
สิ่งนี้ใช้ไม่ได้สำหรับฉัน แต่การเพิ่มคุณสมบัติเพิ่มเติม ng-init ที่แสดงโดย Mark Rajcok (ng-init = "rootFolders = 'Bob'") ทำงานได้ดี
Kaizar Laxmidhar

และฉันจะตั้งค่าเริ่มต้นได้อย่างไรถ้าฉันมีฟิลด์อินพุตเช่น: <input type = "number" ng-model = "newTransaction [$ index] [user.email]" />
ชิช

188

Vojta อธิบายถึง "Angular way" แต่หากคุณต้องการทำให้งานนี้เป็นจริง @urbanek เพิ่งโพสต์วิธีแก้ปัญหาโดยใช้ ng-init:

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

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


33
คุณอาจไม่ต้องการส่วน 'value = "Bob"'
Mark Rajcok

2
+1 แต่ดังที่กล่าวไว้ในหนึ่งในโพสต์ของการสนทนาที่เชื่อมโยงควรหลีกเลี่ยง (เนื่องจากเหตุผลมันถูกต้องน้อยลงและทำให้การทดสอบยากขึ้น)
0xc0de

1
วิธีนี้ใช้งานได้ดีถ้าคุณใช้ค่ารุ่นรวมทั้ง v1.2 <... ng-init = "rootFolders = someModelAttribute" ... >
dmcqu314

@ MarkRajcok คุณมีการโพสต์ AngularJS ที่ยอดเยี่ยมมากมายใน Stack Overflow! ขอบคุณตลอดเวลาที่คุณทุ่มเทให้กับการแบ่งปันข้อมูลเชิงลึกของคุณกับชุมชน SO ฉันแน่ใจว่าฉันพูดกับนักพัฒนาที่โล่งใจหลายคนเมื่อฉันบอกว่าเราขอบคุณทุกเวลาที่คุณได้ช่วยพวกเราอย่างจริงใจ!
Jeremy Moritz

1
ซาบซึ้งกับคำตอบของ Mark มากเพราะช่วยแก้ไขปัญหาของฉันได้ ฉันยืนยันว่าเราไม่ต้องการมีvalue="Bob"ส่วนร่วมในแท็กอินพุต
Devner

68

การเอาชนะคำสั่งอินพุตดูเหมือนว่าจะทำงานได้ ฉันทำการเปลี่ยนแปลงเล็กน้อยกับDan Hunsakerโค้ดของ :

  • เพิ่มการตรวจสอบ ngModel ก่อนพยายามใช้ $parse().assign()กับเขตข้อมูลที่ไม่มีแอตทริบิวต์ ngModel
  • แก้ไขassign()คำสั่งพารามิเตอร์ของฟังก์ชัน
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);
      }
    }
  };
});

นี่คือคำตอบที่ดีที่สุดที่ฉันพบ! ... แก้ปัญหาของฉันอย่างสง่างาม ฉันต้องจับค่าในอินพุตที่ซ่อนอยู่ (โทเค็นฟอร์ม Symfony ซึ่งสร้างขึ้นในเซิร์ฟเวอร์)
PachinSV

นี่ไม่เพียง แต่ฉลาด แต่เป็นทางออกที่ดีที่สุด ในกรณีของฉันฉันไม่สามารถตั้งค่าเริ่มต้นของ ng-model บนคอนโทรลเลอร์ได้เนื่องจากเป็นรูปแบบ PHP หากการตรวจสอบฝั่งเซิร์ฟเวอร์ล้มเหลวแบบฟอร์มจะรีเฟรชและสิ่งที่อยู่ใน ng-model จะหายไปลบค่าอินพุต เกินไป.
Luis Elizondo

2
นี่ดูเหมือนจะเป็นทางออกที่ดีที่สุดหากคุณต้องการให้ฟอร์ม HTML พื้นฐานของคุณทำงานโดยไม่มี JavaScript
Darren

ทางออกที่ยอดเยี่ยมที่ควรจะเป็นตัวเลือกที่ไม่สามารถกำหนดค่าเริ่มต้นได้ภายในเชิงมุมเอง
Gracie

ขอบคุณสำหรับการแก้ปัญหาของคุณ คุณจะแก้ปัญหาการป้อนหมายเลขได้อย่างไร มันส่งข้อผิดพลาดdocs.angularjs.org/error/ngModel/numfmt?p0=20.12
mate.gwozdz

21

วิธีการเชิงมุม

วิธีเชิงมุมที่ถูกต้องในการทำเช่นนี้คือการเขียนแอปพลิเคชันหน้าเดียว AJAX ในเทมเพลตฟอร์มจากนั้นเติมแบบไดนามิกจากโมเดล ค่าเริ่มต้นของแบบจำลองไม่ได้บรรจุจากแบบฟอร์มโดยค่าเริ่มต้นเนื่องจากแบบจำลองเป็นแหล่งความจริงเดียว แต่แองกูลาร์จะไปทางอื่นและพยายามเติมแบบฟอร์มจากแบบจำลอง

อย่างไรก็ตามหากคุณไม่มีเวลาเริ่มต้นใหม่

หากคุณมีแอปที่เขียนขึ้นสิ่งนี้อาจเกี่ยวข้องกับการเปลี่ยนแปลงสถาปัตยกรรมที่ค่อนข้างหนักหน่วง หากคุณกำลังพยายามใช้ Angular เพื่อปรับปรุงแบบฟอร์มที่มีอยู่แทนที่จะสร้างแอปพลิเคชันหน้าเดียวทั้งหมดตั้งแต่ต้นคุณสามารถดึงค่าจากแบบฟอร์มและเก็บไว้ในขอบเขตในเวลาเชื่อมโยงโดยใช้คำสั่ง แองกูลาร์จะผูกค่าในขอบเขตกลับไปที่ฟอร์มและเก็บไว้ในซิงค์

การใช้คำสั่ง

คุณสามารถใช้คำสั่งที่ค่อนข้างง่ายเพื่อดึงค่าจากแบบฟอร์มและโหลดไปยังขอบเขตปัจจุบัน ที่นี่ฉันได้กำหนดคำสั่ง 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);
      }
    };
  });

คุณสามารถเห็นฉันได้กำหนดสองทางเลือกเพื่อรับชื่อรุ่น คุณสามารถใช้คำสั่งนี้ร่วมกับคำสั่ง ngModel หรือผูกติดกับสิ่งอื่นที่ไม่ใช่ $ scope หากคุณต้องการ

ใช้แบบนี้:

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

หมายเหตุสิ่งนี้จะทำงานกับ textareas และเลือกดรอปดาวน์

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

นี่คือโมดูลที่อัดแน่นซึ่งใช้โซลูชันคล้ายกับที่อธิบายไว้ที่นี่github.com/platanus/angular-keep-values
Agustin

1
ทางออกที่ดี input="text"แต่มันจะทำงานร่วมกับ หากคุณมีnumberมันจะโยนโมเดลไม่ใช่ประเภทnumber docs.angularjs.org/error/ngModel/numfmt?p0=333
smoksnes

2
เพื่อรองรับหมายเลขคุณสามารถเพิ่มได้ if (attrs.type === "number") val = parseInt(val);
smoksnes

@smoksnes - คุณถูกต้องอย่างแน่นอน ฉันมีการปรับปรุงคำตอบ :)
superluminary

7

อัปเดต:คำตอบดั้งเดิมของฉันเกี่ยวข้องกับการใช้ตัวควบคุมซึ่งประกอบด้วยรหัส DOM-aware ซึ่งแบ่งการประชุมเชิงมุมเข้ากับ HTML @dmackerman พูดถึงคำสั่งในการแสดงความคิดเห็นในคำตอบของฉันและฉันก็พลาดไปจนตอนนี้ ด้วยอินพุตนั้นต่อไปนี้เป็นวิธีที่ถูกต้องในการทำเช่นนี้โดยไม่แยกการประชุมAngular หรือ HTML:


นอกจากนี้ยังมีวิธีรับทั้งสองอย่าง - รับค่าขององค์ประกอบและใช้สิ่งนั้นเพื่ออัปเดตโมเดลในคำสั่ง:

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

แล้ว:

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);
            }
        }
    };
}]);

แน่นอนคุณสามารถแก้ไขคำสั่งข้างต้นเพื่อทำสิ่งต่างๆได้มากขึ้นด้วยแอvalueททริบิวก่อนที่จะตั้งค่าโมเดลเป็นค่าของมันรวมถึงการใช้$parse(attrs.value, scope)เพื่อรักษาvalueแอตทริบิวต์นั้นเป็นนิพจน์เชิงมุม (แม้ว่าฉันอาจจะใช้แอตทริบิวต์ ดังนั้นแอตทริบิวต์ HTML มาตรฐานจะถือว่าเป็นค่าคงที่)

นอกจากนี้ยังมีคำถามคล้ายกันที่การทำข้อมูลเทมเพลตให้กับรุ่น ngซึ่งอาจเป็นที่สนใจเช่นกัน


คุณไม่ควรทำการจัดการ / ค้นหา DOM ในคอนโทรลเลอร์ของคุณ ควรใช้คำสั่งแทน
dmackerman

2
ฉันได้กล่าวถึงข้อเสียเปรียบอย่างชัดเจนในคำตอบของฉัน คุณไม่ควรแต่คุณสามารถ ทุกอย่างขึ้นอยู่กับว่าคุณพบว่าการติดตามการประชุมของ Angular หรือ HTML สำคัญกว่า เนื่องจาก Angular ทำลาย HTML
Dan Hunsaker

3
โอ้ฉันฉันหลอกตา พลาดเล็กน้อยโดยสิ้นเชิงเกี่ยวกับการใช้คำสั่ง คำตอบอัพเดทตาม ขอแสดงความนับถืออย่างจริงใจที่จะฉุดคุณ @dmackerman
Dan Hunsaker

ขอบคุณสำหรับคำสั่ง! มันทำให้ฉันมีความคิดที่จะนำไปใช้ในโครงการที่ฉันทำงานในที่ที่ฉันสร้างฝั่งเซิร์ฟเวอร์เนื้อหาบางส่วนและจากนั้นจะต้องใช้มันเป็นแบบจำลองของฉันในไคลเอนต์
ggalmazor

ดีใจที่ฉันสามารถช่วย แน่นอนว่าโดยทั่วไปคุณจะต้องสร้างเนื้อหาฝั่งเซิร์ฟเวอร์ของคุณเป็น JSON และให้แอปของคุณจัดการโมเดลตามนั้น แต่บางครั้งมันก็มีประโยชน์ที่จะมีตัวเลือกอื่น ๆ และนี่ก็เป็นหนึ่งในนั้น
Dan Hunsaker

7

หากคุณใช้คำสั่ง AngularJs ngModel โปรดจำไว้ว่าค่าของvalueแอตทริบิวต์ไม่ได้ผูกกับฟิลด์ ngModelคุณต้องเริ่มต้นด้วยตัวคุณเองและวิธีที่ดีที่สุดในการทำคือ

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

รู้สึกแปลกที่จะเริ่มต้นมันในคำสั่ง / มาร์กอัปแทนตัวควบคุม
random_user_name

5

นี่เป็นการแก้ไขคำตอบก่อนหน้าเล็กน้อย ...

ไม่จำเป็นต้องใช้ $ 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;
}]);

โปรดทราบว่า ngModelController $ setViewValue จะเปลี่ยนสถานะของโมเดลเป็นสกปรกและเก่าแก่เป็นเท็จซึ่งจะมีผลต่อสถานะของฟอร์มซึ่งอาจเจ็บปวดได้ในบางครั้ง
Atul Chaudhary

2

สวัสดีคุณสามารถลองวิธีการด้านล่างด้วยการเริ่มต้นของแบบจำลอง

ที่นี่คุณสามารถเริ่มต้น ng-model ของ textbox ได้สองทาง

- ด้วยการใช้ ng-init

- ด้วยการใช้ $ scope ใน 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:'bhatt.bhaskar88@gmail.com',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>                

0

ปัญหาคือคุณต้องตั้งค่า ng-model เป็นองค์ประกอบพาเรนต์ที่คุณต้องการตั้งค่า ng-value / value ดังที่ได้กล่าวไว้โดย Angular:

โดยส่วนใหญ่จะใช้กับอินพุต [วิทยุ] และองค์ประกอบตัวเลือกดังนั้นเมื่อเลือกองค์ประกอบแล้ว ngModel ขององค์ประกอบนั้น (หรือองค์ประกอบหลักที่เลือก) จะถูกตั้งค่าเป็นค่าที่ถูกผูกไว้

เช่น: นี่เป็นรหัสที่เรียกใช้:

<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>

หมายเหตุ: ในกรณีข้างต้นฉัน alreday มีการตอบสนอง JSON ไปยัง ng-model และค่าฉันเพิ่งเพิ่มคุณสมบัติอื่นไปยังวัตถุ JS เป็น "MarketPeers" ดังนั้นรูปแบบและค่าอาจขึ้นอยู่กับความต้องการ แต่ฉันคิดว่ากระบวนการนี้จะช่วยให้มีทั้ง ng-model และ value แต่ไม่มีอยู่ในองค์ประกอบเดียวกัน


0

ฉันมีปัญหาที่คล้ายกัน ฉันไม่สามารถใช้value="something"เพื่อแสดงและแก้ไข ฉันต้องใช้คำสั่งด้านล่างใน<input>รูปแบบของฉันพร้อมกับการประกาศ

[(ngModel)]=userDataToPass.pinCode

ที่ฉันมีรายการของข้อมูลในวัตถุและรายการที่ฉันต้องการที่จะแสดงผลและแก้ไขคือuserDataToPasspinCode

สำหรับเดียวกันฉันเรียก วิดีโอ YouTube นี้


สำหรับวิธีการนี้ OP ใช้ AngularJS การอ้างอิงวิดีโอ YT ของคุณกำลังใช้ Angular 4
Chris22
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.