AngularJS - 当使用 ng-model 时,输入文本框上的 Value 属性会被忽略吗?

IT技术 javascript html angularjs
2021-01-25 01:03:58

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

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

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

6个回答

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

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


function Main($scope) {
  $scope.rootFolders = 'bob';
}
谢谢。但在这种情况下,模型是在控制器中设置的。在 Angular 文档中,它总是相同的,数据设置在控制器中。但是我的控制器在一个 JS 文件中。在“编辑”表单上时怎么办?如何将默认表单数据传递给控制器​​“角度方式”?
2021-04-04 01:03:58
这对我不起作用,但是添加 Mark Rajcok 显示的附加属性 ng-init (ng-init="rootFolders='Bob'") 工作正常。
2021-04-04 01:03:58
如果我有如下输入字段,我该如何设置默认值: <input type="number" ng-model="newTransaction[$index][user.email]" /> ?
2021-04-06 01:03:58

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

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

覆盖输入指令似乎可以完成这项工作。我对Dan Hunsaker的代码做了一些小改动

  • 在尝试$parse().assign()在没有 ngModel 属性的字段上使用之前添加了对 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);
      }
    }
  };
});
感谢您的解决方案。您将如何解决数字输入问题?它抛出一个错误docs.angularjs.org/error/ngModel/numfmt?p0=20.12
2021-03-29 01:03:58
这不仅是聪明的,而且是最好的解决方案。就我而言,我无法在控制器上设置 ng-model 的默认值,因为它是一个 PHP 表单,如果服务器端验证失败,表单将刷新并且 ng-model 中的任何内容都将丢失,删除输入值也。
2021-03-30 01:03:58
优秀的解决方案,它真的应该是 angular 本身的非默认可配置选项。
2021-04-05 01:03:58
这是我找到的最佳答案!...以优雅的方式解决了我的问题。我必须在隐藏输入(服务器中生成的 Symfony 表单令牌)上捕获一个值。
2021-04-07 01:03:58
如果您还希望 HTML 表单的基本版本在没有 JavaScript 的情况下工作,这似乎是最好的解决方案。
2021-04-12 01:03:58

角度方式

正确的 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}}
@smoksnes - 你是绝对正确的。我已经更新了答案:)
2021-03-17 01:03:58
很好的解决方案,但它只适用于input="text". 如果你有number它会抛出Model is not of type number docs.angularjs.org/error/ngModel/numfmt?p0=333
2021-03-21 01:03:58
为了支持您可以添加的数字 if (attrs.type === "number") val = parseInt(val);
2021-04-09 01:03:58
这是一个打包的module,它实现了类似于此处描述的解决方案github.com/platanus/angular-keep-values
2021-04-12 01:03:58

更新:我的原始答案涉及让控制器包含 DOM 感知代码,这打破了支持 HTML 的 Angular 约定。@dmackerman 在对我的回答的评论中提到了指令,直到现在我才完全错过。使用该输入,这是在不破坏 AngularHTML 约定的情况下执行此操作正确方法


还有一种方法可以获得两者 - 获取元素的值并使用它来更新指令中的模型:

<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 属性始终被视为常量)。

此外,在Make data templated in available to ng-model中也有一个类似的问题,这也可能很有趣。

我在回答中明确提到了这个缺点。不应该,但你可以这完全取决于您是否认为遵循 Angular 或 HTML 的约定更重要。因为 Angular 确实破坏了 HTML。
2021-03-14 01:03:58
很高兴我能帮上忙。当然,一般来说,您会希望将服务器端内容构建为 JSON 并让您的应用程序基于此操作模型,但有时拥有其他选项也很有用,这只是其中之一。
2021-03-21 01:03:58
谢谢指点!它给了我一些想法,可以应用到我正在处理的项目中,在该项目中我生成一些内容服务器端,然后必须将其用作客户端中的模型。
2021-03-22 01:03:58
您不应该在控制器中进行任何 DOM 操作/发现。应该使用指令代替。
2021-03-24 01:03:58
哦,我个哑巴。完全错过了使用指令的一点。答案相应更新。@dmackerman 对你的混蛋表示最诚挚的歉意。
2021-04-06 01:03:58