Angular js init ng-модель из значений по умолчанию
скажем, у вас есть форма, которая имеет значения загружаются из базы данных. Как вы инициализируете ng-модель?
пример:
<input name="card[description]" ng-model="card.description" value="Visa-4242">
в моем контроллере, $scope.карта изначально не определена. Есть ли способ сделать что-то подобное?
$scope.card = {
description: $('myinput').val()
}
14 ответов:
Это распространенная ошибка в новых угловых приложениях. Вы не хотите записывать свои значения в свой HTML на сервере, если вы можете этого избежать. Если факт, если вы можете уйти от того, чтобы ваш сервер полностью отображал HTML, тем лучше.
В идеале вы хотите отправить свои угловые HTML-шаблоны, а затем вытащить свои значения через $http в JSON и поместить их в свою область.
поэтому, если это вообще возможно, сделайте следующее:
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; });Я надеюсь, что помогает.
Если вы не можете переработать свое приложение, чтобы сделать то, что предлагает @blesh (вытащить данные JSON с помощью $http или $resource и заполнить $scope), вы можете использовать ng-init вместо:
<input name="card[description]" ng-model="card.description" ng-init="card.description='Visa-4242'">см. также атрибут AngularJS - Value на входном текстовом поле игнорируется, когда используется ng-модель?
это явно не хватает, но легко добавить исправление для 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); } ] }; });
IMHO лучшим решением является директива @Kevin Stone, но мне пришлось обновить ее для работы в любых условиях (например, 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); } } } } });
вы можете использовать пользовательскую директиву (с поддержкой textarea, select, radio и checkbox), проверьте это сообщение в блогеhttps://glaucocustodio.github.io/2014/10/20/init-ng-model-from-form-fields-attributes/.
вы также можете использовать в своем HTML-коде:
ng-init="card.description = 12345"Это не рекомендуется Angular, и, как упоминалось выше, вы должны использовать исключительно свой контроллер.
но это работает :)
У меня простой подход, потому что у меня есть некоторые тяжелые проверки и масок в мои формы. Итак, я использовал jquery, чтобы снова получить свое значение и запустить событие "изменить" на проверки:
$('#myidelement').val('123'); $('#myidelement').trigger( "change");
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; });таким образом, представления не содержат данных, и контроллер инициализирует значение во время загрузки реальных значений.
Если вам нравится подход Кевина Стоуна выше 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 к каждому тегу. Он автоматически устанавливает значение модели в атрибут значения тега. Если вы не установите значение атрибута по умолчанию будет пустая строка.
вот сервер-ориентированный подход:
<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.значение регистрирует сервис, содержащий значения по умолчанию.
Итак, на сервере, вы могли бы иметь что-то вроде:
{ description: "Visa-4242" }и поместите его на свою страницу через серверную технологию по вашему выбору. Вот суть:https://gist.github.com/exclsr/c8c391d16319b2d31a43
это более общая версия идей, упомянутых выше... Он просто проверяет, есть ли какое-либо значение в модели, и если нет, он устанавливает значение для модели.
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>
я попробовал то, что предложил @Mark Rajcok. Его работа для строковых значений (Visa-4242). Пожалуйста, обратитесь к этому скрипка.
от скрипки:
то же самое, что делается в скрипку можно сделать с помощью
ng-repeat, который каждый мог бы рекомендовать. Но после прочтения ответа, данного @Mark Rajcok, я просто хотел попробовать то же самое для формы с массивом профилей. Все работает хорошо, пока у меня есть $ scope.профили = [{},{}]; код в контроллере. Если я удалить этот код, я получаю ошибки. Но в обычных сценариях я не могу печатать$scope.profiles = [{},{}];Как я печатаю или эхо html с сервера. Будет ли возможно выполнить вышеизложенное, аналогично тому, как @Mark Rajcok сделал для строковых значений, таких как<input name="card[description]" ng-model="card.description" ng-init="card.description='Visa-4242'">, без необходимости повторять часть JavaScript с сервера.
просто добавлена поддержка select element для Ryan Montgomery "fix"
<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) }] }});
Если у вас есть значение инициализации в URL, например
mypage/id, то в контроллере угловой JS вы можете использоватьlocation.pathnameчтобы найти идентификатор и присвоить его нужной модели.
Comments