126

假设您有一个从数据库加载值的表单。你如何初始化 ng-model?

例子:

<input name="card[description]" ng-model="card.description" value="Visa-4242">

在我的控制器中, $scope.card 最初是未定义的。除了做这样的事情,还有什么办法吗?

$scope.card = {
  description: $('myinput').val()
}
4

14 回答 14

237

如果您无法按照@blesh 的建议重新设计您的应用程序(使用 $http 或 $resource 下拉 JSON 数据并填充 $scope),您可以改用ng-init

<input name="card[description]" ng-model="card.description" ng-init="card.description='Visa-4242'">

另请参阅AngularJS - 使用 ng-model 时忽略输入文本框上的值属性?

于 2012-12-08T06:31:47.137 回答
136

这是新 Angular 应用程序中的常见错误。如果可以避免的话,您不想将值写入服务器上的 HTML。事实上,如果您可以避免让服务器完全呈现 HTML,那就更好了。

理想情况下,您希望发送您的 Angular HTML 模板,然后通过 JSON 中的 $http 提取您的值并将它们放入您的范围。

因此,如果可能,请执行以下操作:

app.controller('MyController', function($scope, $http) {
    $http.get('/getCardInfo.php', function(data) {
       $scope.card = data;
    });
});

<input type="text" ng-model="card.description" />

如果您绝对必须将您的值从您的服务器呈现到您的 HTML 中,您可以将它们放在一个全局变量中并使用 $window 访问它们:

在页面的标题中,您会写出:

<head>
   <script>
       window.card = { description: 'foo' };
   </script>
</head>

然后在你的控制器中你会得到它:

app.controller('MyController', function($scope, $window) {
   $scope.card = $window.card;
});

我希望这会有所帮助。

于 2012-12-07T21:24:44.350 回答
60

这是 AngularJS 的一个明显缺乏但很容易添加的修复。只需编写一个快速指令即可从输入字段设置模型值。

<input name="card[description]" value="Visa-4242" ng-model="card.description" ng-initial>

这是我的版本:

var app = angular.module('forms', []);

app.directive('ngInitial', function() {
  return {
    restrict: 'A',
    controller: [
      '$scope', '$element', '$attrs', '$parse', function($scope, $element, $attrs, $parse) {
        var getter, setter, val;
        val = $attrs.ngInitial || $attrs.value;
        getter = $parse($attrs.ngModel);
        setter = getter.assign;
        setter($scope, val);
      }
    ]
  };
});
于 2013-07-24T01:12:13.033 回答
12

恕我直言,最好的解决方案是@Kevin Stone 指令,但我必须升级它才能在各种条件下工作(fe select、textarea),而这个肯定可以工作:

    angular.module('app').directive('ngInitial', function($parse) {
        return {
            restrict: "A",
            compile: function($element, $attrs) {
                var initialValue = $attrs.value || $element.val();
                return {
                    pre: function($scope, $element, $attrs) {
                        $parse($attrs.ngModel).assign($scope, initialValue);
                    }
                }
            }
        }
    });
于 2014-02-13T14:22:20.987 回答
7

您可以使用自定义指令(支持 textarea、select、radio 和 checkbox),查看这篇博文https://glaucocustodio.github.io/2014/10/20/init-ng-model-from-form-字段属性/

于 2014-10-20T20:09:30.943 回答
6

您还可以在 HTML 代码中使用: ng-init="card.description = 12345"

Angular 不建议这样做,如上所述,您应该专门使用您的控制器。

但它有效:)

于 2014-10-16T04:30:25.390 回答
4

我有一个简单的方法,因为我的表单中有一些繁重的验证和掩码。因此,我使用 jquery 再次获取我的值并将事件“更改”触发到验证:

$('#myidelement').val('123');
$('#myidelement').trigger( "change");
于 2016-01-18T01:39:09.377 回答
3

正如其他人指出的那样,在视图上初始化数据并不是一个好习惯。但是,建议在 Controller 上初始化数据。(见http://docs.angularjs.org/guide/controller

所以你可以写

<input name="card[description]" ng-model="card.description">

$scope.card = { description: 'Visa-4242' };

$http.get('/getCardInfo.php', function(data) {
   $scope.card = data;
});

这样视图不包含数据,并且控制器在加载实际值时初始化值。

于 2014-03-13T12:54:31.640 回答
3

如果您喜欢 Kevin Stone 在https://stackoverflow.com/a/17823590/584761上的方法,请 考虑通过为特定标签(例如“输入”)编写指令来更简单的方法。

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

如果你走这条路,你就不必担心将 ng-initial 添加到每个标签。它自动将模型的值设置为标签的 value 属性。如果您不设置 value 属性,它将默认为空字符串。

于 2014-03-21T19:07:39.943 回答
3

这是一种以服务器为中心的方法:

<html ng-app="project">
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <script>
        // Create your module
        var dependencies = [];
        var app = angular.module('project', dependencies);

        // Create a 'defaults' service
        app.value("defaults", /* your server-side JSON here */);

        // Create a controller that uses the service
        app.controller('PageController', function(defaults, $scope) {
            // Populate your model with the service
            $scope.card = defaults;
        });
    </script>

    <body>
        <div ng-controller="PageController">
            <!-- Bind with the standard ng-model approach -->
            <input type="text" ng-model="card.description">
        </div>
    </body>
</html>

除了$provide.value注册了一个包含您的默认值的服务之外,这与此问题上更流行的答案的基本思想相同。

所以,在服务器上,你可以有类似的东西:

{
    description: "Visa-4242"
}

并通过您选择的服务器端技术将其放入您的页面。这是一个要点:https ://gist.github.com/exclsr/c8c391d16319b2d31a43

于 2014-09-04T01:33:51.683 回答
1

这个是上面提到的想法的一个更通用的版本......它只是检查模型中是否有任何值,如果没有,它将值设置给模型。

JS:

function defaultValueDirective() {
    return {
        restrict: 'A',
        controller: [
            '$scope', '$attrs', '$parse',
            function ($scope, $attrs, $parse) {
                var getter = $parse($attrs.ngModel);
                var setter = getter.assign;
                var value = getter();
                if (value === undefined || value === null) {
                    var defaultValueGetter = $parse($attrs.defaultValue);
                    setter($scope, defaultValueGetter());
                }
            }
        ]
    }
}

HTML(使用示例):

<select class="form-control"
        ng-options="v for (i, v) in compressionMethods"
        ng-model="action.parameters.Method"
        default-value="'LZMA2'"></select>
于 2016-01-17T22:12:19.780 回答
0

我尝试了@Mark Rajcok 的建议。它适用于字符串值(Visa-4242)。请参考这个小提琴

从小提琴:

在小提琴中完成的同样的事情可以使用 来完成ng-repeat,每个人都可以推荐。但是在阅读了@Mark Rajcok 给出的答案之后,我只是想尝试对具有配置文件数组的表单进行相同的操作。在我拥有 $scope.profiles = [{},{}]; 之前一切正常 控制器中的代码。如果我删除此代码,我会收到错误消息。但在正常情况下$scope.profiles = [{},{}]; ,当我从服务器打印或回显 html 时,我无法打印。是否有可能以与@Mark Rajcok 对字符串值类似的方式执行上述操作<input name="card[description]" ng-model="card.description" ng-init="card.description='Visa-4242'">,而不必从服务器回显 JavaScript 部分。

于 2013-02-20T03:32:49.947 回答
0

刚刚向 Ryan Montgomery “修复”添加了对选择元素的支持

<select class="input-control" ng-model="regCompModel.numberOfEmployeeId" ng-initial>
    <option value="1af38656-a752-4a98-a827-004a0767a52d"> More than 500</option>
    <option value="233a2783-db42-4fdb-b191-0f97d2d9fd43"> Between 250 and 500</option>
    <option value="2bab0669-550c-4555-ae9f-1fdafdb872e5"> Between 100 and 250</option>
    <option value="d471e43b-196c-46e0-9b32-21e24e5469b4"> Between 50 and 100</option>
    <option value="ccdad63f-69be-449f-8b2c-25f844dd19c1"> Between 20 and 50</option>
    <option value="e00637a2-e3e8-4883-9e11-94e58af6e4b7" selected> Less then 20</option>
</select>

app.directive('ngInitial', function () {
return {
    restrict: 'A',
    controller: ['$scope', '$element', '$attrs', '$parse', function ($scope, $element, $attrs, $parse) {
        val = $attrs.sbInitial || $attrs.value || $element.val() || $element.text()
        getter = $parse($attrs.ngModel)
        setter = getter.assign
        setter($scope, val)
    }]
}

});

于 2014-02-01T10:45:12.877 回答
0

如果您在 URL 中有 init 值mypage/id,那么在 Angular JS 的控制器中,您可以使用location.pathname它来查找 id 并将其分配给您想要的模型。

于 2014-07-31T05:49:40.810 回答