AngularJS - Атрибут значения в текстовом поле ввода игнорируется, когда используется ng-модель?


219

Использование AngularJS, если я установил значение простого текстового поля на что-то вроде «bob» ниже. Значение не отображается, если ng-modelатрибут добавлен.

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

Кто-нибудь знает простой способ обойти этот ввод по умолчанию и сохранить ng-model? Я попытался использовать ng-bindсо значением по умолчанию, но это, похоже, тоже не работает.

Ответы:


223

Это желаемое поведение, вы должны определить модель в контроллере, а не в представлении.

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


function Main($scope) {
  $scope.rootFolders = 'bob';
}

11
Спасибо. Но в этом случае модель устанавливается в контроллере. И в Angular Docs, это всегда то же самое, данные устанавливаются в контроллере. Но мой контроллер находится в файле JS. Как это сделать, когда в форме «редактировать»? Как передать данные формы по умолчанию в контроллер "угловым путем"?
ByScripts

8
Это не работает для меня, однако добавление дополнительного атрибута ng-init, показанного Марком Райкоком (ng-init = "rootFolders = 'Bob'"), работает нормально.
Кайзар Лаксмидхар

И как мне установить значение по умолчанию, если у меня есть поле ввода, например: <input type = "number" ng-model = "newTransaction [$ index] [user.email]" />?
Shish

188

Войта описал «угловой путь», но если вам действительно нужно сделать эту работу, @urbanek недавно опубликовал обходной путь, используя ng-init:

<input type="text" ng-model="rootFolders" ng-init="rootFolders='Bob'" value="Bob">

https://groups.google.com/d/msg/angular/Hn3eztNHFXw/wk3HyOl9fhcJ


33
Вам может не понадобиться часть 'value = "Bob".
Марк Райкок

2
+1, но, как упомянуто в одном из постов в связанном обсуждении, этого следует избегать (так как по логике это менее правильно и затрудняет тестирование).
0xc0de

1
Этот метод работает хорошо, если вы используете значение модели также на v1.2. <... ng-init = "rootFolders = someModelAttribute" ...>
dmcqu314

@MarkRajcok, у вас так много замечательных сообщений на AngularJS о переполнении стека! Спасибо за все то время, которое вы посвятили тому, чтобы поделиться своими идеями с SO-сообществом. Я уверен, что говорю от имени многих разработчиков, когда говорю, что мы искренне ценим все часы, которые вы нам спасли!
Джереми Мориц

1
Очень ценю ответ Марка, который решил мою проблему. Я подтверждаю, что нам НЕ нужна value="Bob"часть входного тега.
Девнер

68

Переопределение директивы input, похоже, делает свою работу. Я внес небольшие изменения в код Дэна Хансакера :

  • Добавлена ​​проверка для ngModel, прежде чем пытаться использовать $parse().assign()в полях без атрибутов 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);
      }
    }
  };
});

Это лучший ответ, который я нашел! ... элегантно решает мою проблему. Мне пришлось записать значение на скрытый вход (токен формы Symfony, созданный на сервере).
PachinSV

Это не только умное, но и лучшее решение. В моем случае я не могу установить значение по умолчанию для ng-модели на контроллере, потому что это форма PHP, если проверка на стороне сервера завершится неудачно, форма обновится и все, что находится в ng-модели, будет потеряно при удалении входного значения слишком.
Луис Элизондо

2
Это кажется лучшим решением, если вы также хотите, чтобы базовая версия HTML-формы работала без JavaScript.
Даррен

Отличное решение, которое на самом деле должно быть нестандартным настраиваемым параметром внутри самого angular.
Грейси

Спасибо за ваше решение. Как бы вы решили проблему ввода чисел? Выдает
mate.gwozdz

21

Угловой путь

Правильный способ сделать это - написать одностраничное приложение 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}}

Обратите внимание, что это также будет работать с текстовыми областями и выбирать выпадающие списки.

<textarea name="test" ng-model="toaster.test" init-from-form>hello</textarea>
{{toaster.test}}

Вот упакованный модуль, который реализует решение, подобное тому, что описано здесь github.com/platanus/angular-keep-values
Агустин

1
Отличное решение, но оно будет работать только с input="text". Если у вас есть, numberон выдаст Модель не типа number docs.angularjs.org/error/ngModel/numfmt?p0=333
Smoksnes

2
Для поддержки номеров вы можете добавить if (attrs.type === "number") val = parseInt(val);
Smoksnes

@smoksnes - вы абсолютно правы. Я обновил ответ :)
superluminary

7

Обновление: Мой первоначальный ответ состоял в том, чтобы контроллер содержал код с поддержкой DOM, который нарушает соглашения Angular в пользу HTML. @dmackerman упомянул директивы в комментарии к моему ответу, и я до сих пор совершенно не замечал этого. С этим вводом вот правильный способ сделать это, не нарушая соглашения Angular или HTML:


Есть также способ получить и то и другое - получить значение элемента и использовать его для обновления модели в директиве:

<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атрибута как углового выражения (хотя я бы, вероятно, использовал для этого другой атрибут [custom], лично поэтому стандартные атрибуты HTML постоянно рассматриваются как константы).

Кроме того, возникает аналогичный вопрос в разделе «Создание данных, шаблонизированных в доступной для ng-модели», что также может представлять интерес.


Вы не должны делать какие-либо манипуляции / обнаружение DOM в ваших контроллерах. Вместо этого следует использовать директиву.
dmackerman

2
Я явно упомянул этот недостаток в своем ответе. Вы не должны , но вы можете . Все зависит от того, считаете ли вы более важным следовать соглашениям Angular или HTML. Потому что Angular ломает HTML.
Дэн Хансакер

3
О, я являюсь фиктивным. Полностью пропустил немного об использовании директивы. Ответ обновлен соответственно. Искренне извиняюсь за то, что был придурком, @dmackerman.
Дэн Хансакер

Спасибо за директиву! Это дало мне идеи для применения в проекте, над которым я работаю, где я генерирую некоторую сторону контент-сервера и затем должен использовать его как свою модель в клиенте.
Ггалмазор

Рад, что смог помочь. Конечно, вообще говоря, вы захотите построить свой серверный контент как JSON, и ваше приложение будет манипулировать моделью на основе этого, но иногда полезно иметь другие опции, и это только один из них.
Дан Хансакер

7

Если вы используете директиву AngularJs ngModel, помните, что значение valueатрибута не связывается с полем ngModel. Вы должны инициировать его самостоятельно, и лучший способ сделать это

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

Чувствует себя странно, чтобы инициировать его в директиве / разметке вместо контроллера.
random_user_name

5

Это небольшая модификация предыдущих ответов ...

Нет необходимости в $ parse

angular.directive('input', [function () {
  'use strict';

  var directiveDefinitionObject = {
    restrict: 'E',
    require: '?ngModel',
    link: function postLink(scope, iElement, iAttrs, ngModelController) {
      if (iAttrs.value && ngModelController) {
        ngModelController.$setViewValue(iAttrs.value);
      }
    }
  };

  return directiveDefinitionObject;
}]);

имейте в виду, что ngModelController. $ setViewValue изменит состояние модели на грязное и нетронутое на ложное, что также повлияет на состояние формы, что может иногда вызывать боль.
Атул Чаудхари

2

Привет, вы можете попробовать ниже методы с инициализацией модели.

Здесь вы можете инициализировать ng-модель текстового поля двумя способами

- с использованием ng-init

- с использованием $ scope в js

<!doctype html>
 <html >
 <head>
        <title>Angular js initalize with ng-init and scope</title>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
</head>
<body ng-app="app" >
    <h3>Initialize value with ng-init</h3>
    <!-- Initlialize model values with ng-init -->
    <div ng-init="user={fullname:'Bhaskar Bhatt',email:'bhatt.bhaskar88@gmail.com',address:'Ahmedabad'};">
        Name : <input type="text" ng-model="user.fullname" /><br/>
        Email : <input type="text" ng-model="user.email" /><br/>
        Address:<input type="text" ng-model="user.address" /><br/>

    </div>  
    <!-- initialize with js controller scope -->
    <h3>Initialize with js controller</h3>

    <div  ng-controller="alpha">
        Age:<input type="text" name="age" ng-model="user.age" /><br/>
        Experience : <input type="text" name="experience" ng-model="user.exp" /><br/>
        Skills : <input type="text" name="skills" ng-model="user.skills" /><br/>
    </div>  

</body> 
<script type="text/javascript">
        angular.module("app",[])
        .controller("alpha",function($scope){
            $scope.user={};
            $scope.user.age=27;
            $scope.user.exp="4+ years";
            $scope.user.skills="Php,javascript,Jquery,Ajax,Mysql";
        });

     </script>
 </html>                

0

Проблема в том, что вы должны установить ng-модель для родительского элемента, где вы хотите установить ng-значение / значение. Как упомянуто Angular:

Он в основном используется для элементов input [radio] и option, поэтому при выборе элемента для ngModel этого элемента (или его родительского элемента select) устанавливается значение привязки.

Например: это исполняемый код:

<div class="col-xs-12 select-checkbox" >
<label style="width: 18em;" ng-model="vm.settingsObj.MarketPeers">
  <input name="radioClick" type="radio"  ng-click="vm.setPeerGrp('market');" 
         ng-value="vm.settingsObj.MarketPeers" 
         style="position:absolute;margin-left: 9px;">
  <div style="margin-left: 35px;color: #717171e8;border-bottom: 0.5px solid #e2e2e2;padding-bottom: 2%;">Hello World</div>
</label>
</div>

Примечание. В приведенном выше случае у меня уже был ответ JSON на ng-модель и значение, я просто добавляю другое свойство к объекту JS как «MarketPeers». Таким образом, модель и значение могут зависеть от необходимости, но я думаю, что этот процесс поможет иметь и модель ng, и значение, но не иметь их на одном элементе.


0

У меня была похожая проблема. Я не смог использовать value="something"для отображения и редактирования. Я должен был использовать нижеприведенную команду внутри моей <input>модели с объявленной моделью.

[(ngModel)]=userDataToPass.pinCode

Где у меня есть список данных в объекте userDataToPassи элемент, который мне нужно отобразить и отредактироватьpinCode .

Для того же я ссылался на это видео на YouTube


Для этого, как OP использует AngularJS, ваша ссылка на видео YT использует Angular 4.
Chris22
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.