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

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

Пример:

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

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

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

Ответ 1

Это распространенная ошибка в новых приложениях Angular. Вы не хотите записывать свои значения в свой HTML на сервере, если можете избежать этого. Если факт, если вы можете уйти от того, чтобы ваш сервер полностью отображал HTML, тем лучше.

В идеале вы хотите отправить свои HTML-шаблоны Angular, а затем потяните свои значения через $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;
});

Я надеюсь, что это поможет.

Ответ 2

Если вы не можете переделать свое приложение, чтобы сделать то, что предлагает @blesh (вытащите данные JSON вниз с помощью $http или $resource и заполните пробел $), вы можете использовать ng-init:

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

См. также AngularJS - Атрибут Value во входном текстовом поле игнорируется при использовании ng-модели?

Ответ 3

Это явно недостающее, но легко добавленное исправление для 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);
      }
    ]
  };
});

Ответ 4

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);
                    }
                }
            }
        }
    });

Ответ 6

Вы также можете использовать код HTML: ng-init="card.description = 12345"

Не рекомендуется использовать Angular, и, как упоминалось выше, вы должны использовать исключительно ваш контроллер.

Но он работает:)

Ответ 7

У меня простой подход, потому что у меня есть некоторые тяжелые проверки и маски в моих формах. Итак, я использовал jquery, чтобы снова получить мое значение и запустить событие "change" для проверки:

$('#myidelement').val('123');
$('#myidelement').trigger( "change");

Ответ 8

Как указывали другие, нецелесообразно инициализировать данные по представлениям. Однако рекомендуется инициализировать данные на контроллерах. (см. 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;
});

Таким образом, представления не содержат данных, а контроллер инициализирует значение при загрузке реальных значений.

Ответ 9

Если вам нравится подход Кевина Стоуна выше fooobar.com/questions/47004/... рассмотрите более простой подход, написав директивы для определенных тегов, таких как "enter".

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, по умолчанию будет пустая строка.

Ответ 10

Вот ориентированный на сервер подход:

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

Это та же основная идея, что и более популярные ответы на этот вопрос, кроме $provided.value регистрирует сервис, который содержит ваши значения по умолчанию.

Итак, на сервере у вас может быть что-то вроде:

{
    description: "Visa-4242"
}

И разместите его на своей странице с помощью технологии на стороне сервера по вашему выбору. Здесь Gist: https://gist.github.com/exclsr/c8c391d16319b2d31a43

Ответ 11

Я попробовал, что предложил @Mark Rajcok. Он работает для значений String (Visa-4242). Пожалуйста, обратитесь к fiddle.

Из скрипта:

То же самое, что сделано в скрипке, можно сделать с помощью ng-repeat, который каждый мог бы порекомендовать. Но после прочтения ответа, данного @Mark Rajcok, я просто хотел попробовать то же самое для формы с массивом профилей. Все работает хорошо, пока у меня нет $scope.profiles = [{}, {}]; кода в контроллере. Если я удалю этот код, я получаю ошибки. Но в обычных сценариях я не могу напечатать $scope.profiles = [{},{}]; как я print или echo html с сервера. Можно ли выполнить описанное выше, аналогично тому, как @Mark Rajcok сделал для строковых значений, таких как <input name="card[description]" ng-model="card.description" ng-init="card.description='Visa-4242'">, без необходимости отгонять часть JavaScript с сервера.

Ответ 12

Это более общая версия упомянутых выше идей... Он просто проверяет, есть ли какое-либо значение в модели, а если нет, оно задает значение модели.

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>

Ответ 13

Просто добавлена ​​поддержка выбранного элемента для 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)
    }]
}

});

Ответ 14

Если у вас есть значение init в URL, например mypage/id, то в контроллере angular JS вы можете использовать location.pathname, чтобы найти идентификатор и назначить его желаемой модели.