Angular js init ng-модель из значений по умолчанию



скажем, у вас есть форма, которая имеет значения загружаются из базы данных. Как вы инициализируете ng-модель?



пример:



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


в моем контроллере, $scope.карта изначально не определена. Есть ли способ сделать что-то подобное?



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

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

    Ничего не найдено.