HelloWorld
HelloWorld

Reputation: 4349

AngularJS - Value attribute on an input text box is ignored when there is a ng-model used?

Using AngularJS if I set a simple input text box value to something like "bob" below. The value does not display if the ng-model attribute is added.

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

Anyone know of a simple work around to default this input to something and keep the ng-model? I tried to use a ng-bind with the default value but that seems not to work either.

Upvotes: 222

Views: 416179

Answers (10)

trupthi
trupthi

Reputation: 81

I had similar issue. I was not able to use value="something" to display and edit. I had to use the below command inside my <input>along withe ng model being declared.

[(ngModel)]=userDataToPass.pinCode

Where I have the list of data in the object userDataToPass and the item that I need to display and edit is pinCode.

For the same , I referred to this YouTube video

Upvotes: 0

Ivan Breet
Ivan Breet

Reputation: 680

Overriding the input directive does seem to do the job. I made some minor alterations to Dan Hunsaker's code:

  • Added a check for ngModel before trying to use $parse().assign() on fields without a ngModel attributes.
  • Corrected the assign() function param order.
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);
      }
    }
  };
});

Upvotes: 68

sg28
sg28

Reputation: 1387

The issue is that you have to set the ng-model to the parent element to where you want to set the ng-value/value . As mentioned by Angular:

It is mainly used on input[radio] and option elements, so that when the element is selected, the ngModel of that element (or its select parent element) is set to the bound value.

Eg:This is an executed code :

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

Note: In this above case I alreday had the JSON response to the ng-model and the value, I am just adding another property to the JS object as "MarketPeers". So the model and value may depend according to the need, but I think this process will help, to have both ng-model and value but not having them on the same element.

Upvotes: 0

Bhaskar Bhatt
Bhaskar Bhatt

Reputation: 1467

Hi you can try below methods with initialize of model.

Here you can initialize ng-model of textbox two way

- With use of ng-init

- With use of $scope in 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:'[email protected]',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>                

Upvotes: 2

superluminary
superluminary

Reputation: 49132

The Angular way

The correct Angular way to do this is to write a single page app, AJAX in the form template, then populate it dynamically from the model. The model is not populated from the form by default because the model is the single source of truth. Instead Angular will go the other way and try to populate the form from the model.

If however, you don't have time to start over from scratch

If you have an app written, this might involve some fairly hefty architectural changes. If you're trying to use Angular to enhance an existing form, rather than constructing an entire single page app from scratch, you can pull the value from the form and store it in the scope at link time using a directive. Angular will then bind the value in the scope back to the form and keep it in sync.

Using a directive

You can use a relatively simple directive to pull the value from the form and load it in to the current scope. Here I've defined an initFromForm directive.

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

You can see I've defined a couple of fallbacks to get a model name. You can use this directive in conjunction with the ngModel directive, or bind to something other than $scope if you prefer.

Use it like this:

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

Note this will also work with textareas, and select dropdowns.

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

Upvotes: 21

Hazarapet Tunanyan
Hazarapet Tunanyan

Reputation: 2865

If you use AngularJs ngModel directive, remember that the value of value attribute does not bind on ngModel field.You have to init it by yourself and the best way to do it,is

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

Upvotes: 7

dale.lotts
dale.lotts

Reputation: 419

This is a slight modification to the earlier answers...

There is no need for $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;
}]);

Upvotes: 5

Dan Hunsaker
Dan Hunsaker

Reputation: 309

Update: My original answer involved having the controller contain DOM-aware code, which breaks Angular conventions in favor of HTML. @dmackerman mentioned directives in a comment on my answer, and I completely missed that until just now. With that input, here's the right way to do this without breaking Angular or HTML conventions:


There's also a way to get both - grab the value of the element and use that to update the model in a directive:

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

and then:

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

You can of course modify the above directive to do more with the value attribute before setting the model to its value, including using $parse(attrs.value, scope) to treat the value attribute as an Angular expression (though I'd probably use a different [custom] attribute for that, personally, so the standard HTML attributes are consistently treated as constants).

Also, there is a similar question over at Making data templated in available to ng-model which may also be of interest.

Upvotes: 7

Mark Rajcok
Mark Rajcok

Reputation: 364677

Vojta described the "Angular way", but if you really need to make this work, @urbanek recently posted a workaround using ng-init:

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

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

Upvotes: 189

Vojta
Vojta

Reputation: 23051

That's desired behavior, you should define the model in the controller, not in the view.

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


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

Upvotes: 224

Related Questions