【问题标题】:AngularJS - Value attribute on an input text box is ignored when there is a ng-model used?AngularJS - 使用 ng-model 时忽略输入文本框上的值属性?
【发布时间】:2012-05-23 12:40:46
【问题描述】:

如果我将一个简单的输入文本框值设置为下面的“bob”,则使用 AngularJS。如果添加了ng-model 属性,则不会显示该值。

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

任何人都知道一个简单的解决方法来将此输入默认为某些东西并保留ng-model?我尝试使用带有默认值的ng-bind,但这似乎也不起作用。

【问题讨论】:

    标签: javascript html angularjs


    【解决方案1】:

    我有类似的问题。我无法使用value="something" 来显示和编辑。 我必须在我的&lt;input&gt;中使用以下命令,同时声明模型。

    [(ngModel)]=userDataToPass.pinCode
    

    我有对象userDataToPass 中的数据列表,我需要显示和编辑的项目是pinCode

    同样,我提到了this YouTube video

    【讨论】:

    • 对于这个 howTo,OP 使用的是 AngularJS,你的 YT 视频参考使用的是 Angular 4。
    【解决方案2】:

    覆盖输入指令似乎确实可以完成这项工作。我对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 表单令牌)上捕获一个值。
    • 这不仅聪明而且是最好的解决方案。就我而言,我无法在控制器上设置 ng-model 的默认值,因为它是一个 PHP 表单,如果服务器端验证失败,表单将刷新并且 ng-model 中的任何内容都将丢失,删除输入值也是。
    • 如果您还希望 HTML 表单的基本版本在没有 JavaScript 的情况下工作,这似乎是最好的解决方案。
    • 优秀的解决方案,确实应该是 Angular 本身的非默认可配置选项。
    • 感谢您的解决方案。您将如何解决数字输入问题?它会引发错误docs.angularjs.org/error/ngModel/numfmt?p0=20.12
    【解决方案3】:

    问题是您必须将 ng-model 设置为要设置 ng-value/value 的父元素。 正如 Angular 所说:

    主要用在input[radio]和option元素上,这样当元素被选中时,该元素(或者它的select父元素)的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>
    

    注意:在上述情况下,我已经收到了对 ng-model 和值的 JSON 响应,我只是将另一个属性添加到 JS 对象作为“MarketPeers”。所以模型和价值可能取决于需要,但我认为这个过程会有所帮助,同时拥有 ng-model 和 value 但不在同一个元素上。

    【讨论】:

      【解决方案4】:

      您好,您可以尝试以下方法初始化模型。

      这里可以两种方式初始化文本框的ng-model

      - 使用 ng-init

      - 在 js 中使用 $scope

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

      【讨论】:

        【解决方案5】:

        角度方式

        正确的 Angular 方法是在表单模板中编写单页应用程序 AJAX,然后从模型中动态填充它。默认情况下,模型不会从表单中填充,因为模型是唯一的事实来源。相反,Angular 会采用另一种方式,并尝试从模型中填充表单。

        但是,如果您没有时间从头开始

        如果您编写了一个应用程序,这可能涉及一些相当大的架构更改。如果您尝试使用 Angular 来增强现有表单,而不是从头开始构建整个单页应用程序,您可以从表单中提取值并在链接时使用指令将其存储在范围中。然后,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}}
        

        【讨论】:

        【解决方案6】:

        如果你使用AngularJs ngModel指令,请记住value属性的值不绑定在ngModel字段上。你必须自己初始化它,最好的方法是

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

        【讨论】:

        • 在指令/标记而不是控制器中初始化它感觉很奇怪。
        【解决方案7】:

        这是对之前答案的轻微修改...

        不需要$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 会将模型状态更改为脏状态并将原始状态更改为 false,这也会影响表单状态,这在一段时间内可能会很痛苦。
        【解决方案8】:

        更新:我最初的回答是让控制器包含可识别 DOM 的代码,这打破了 Angular 的约定以支持 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 属性视为 Angular 表达式(尽管我可能会就个人而言,为此使用不同的 [custom] 属性,因此标准的 HTML 属性始终被视为常量)。

        另外,Making data templated in available to ng-model 也有类似的问题,可能也很有趣。

        【讨论】:

        • 您不应该在控制器中进行任何 DOM 操作/发现。应该使用指令。
        • 我在回答中明确提到了这个缺点。你不应该,但你可以。这完全取决于您是否发现遵循 Angular 或 HTML 的约定更重要。因为 Angular 确实破坏了 HTML。
        • 哦,我一个假人。完全错过了关于使用指令的一点。答案相应更新。最诚挚的道歉,@dmackerman,你是个混蛋。
        • 感谢您的指导!它给了我一些想法,可以将其应用到我正在处理的项目中,在该项目中我生成一些内容服务器端,然后必须将其用作客户端中的模型。
        • 很高兴我能帮上忙。当然,一般来说,您会希望将您的服务器端内容构建为 JSON,并让您的应用基于它来操作模型,但有时还有其他选项很有用,这只是其中之一。
        【解决方案9】:

        Vojta 描述了“Angular 方式”,但如果你真的需要完成这项工作,@urbanek 最近发布了一个使用 ng-init 的解决方法:

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

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

        【讨论】:

        • 你可能不需要 'value="Bob"' 部分。
        • +1 但是,正如链接讨论中的一篇文章中提到的那样,应该避免它(因为从逻辑上讲它不太正确并且它使测试更加困难)。
        • 如果您在 v1.2 上也使用模型值,则此方法可以正常工作。 <... ng-init="rootFolders=someModelAttribute" ...>
        • @MarkRajcok,你在 Stack Overflow 上有很多很棒的 AngularJS 帖子!感谢您花时间与 S.O. 分享您的见解。社区。当我说我们真诚地感谢您为我们节省的所有时间时,我确信我代表了许多松了一口气的开发人员!
        • 非常感谢马克的回答,因为它解决了我的问题。我确实确认我们不需要输入标签中的value="Bob" 部分。
        【解决方案10】:

        这是期望的行为,您应该在控制器中定义模型,而不是在视图中。

        <div ng-controller="Main">
          <input type="text" ng-model="rootFolders">
        </div>
        
        
        function Main($scope) {
          $scope.rootFolders = 'bob';
        }
        

        【讨论】:

        • 谢谢。但是在这种情况下,模型是在控制器中设置的。在 Angular 文档中,它总是一样的,数据是在控制器中设置的。但我的控制器在一个 JS 文件中。在“编辑”表单上怎么办?如何以“角度方式”将默认表单数据传递给控制器​​?
        • 这对我不起作用,但是添加 Mark Rajcok (ng-init="rootFolders='Bob'") 显示的附加属性 ng-init 可以正常工作。
        • 如果我有这样的输入字段,我该如何设置默认值:
        猜你喜欢
        • 2015-01-27
        • 2016-01-16
        • 1970-01-01
        • 2015-04-05
        • 2021-01-19
        • 2014-12-20
        • 1970-01-01
        • 1970-01-01
        • 2019-04-20
        相关资源
        最近更新 更多