AngularJS data binding not working - within the controller Scope variables are not showing the entered value - javascript

I have a strange situation in which $scope variables binding do not appear to be work as expected.
Here is the HTML:
<div class="input-group" style="width:100px">
<input type="number"
class="form-control"
id="Sampling_Request_for_Current_Sampling_INPUT"
ng-model="aabbcc"
style="width:125px;text-align:center">
<span class="input-group-btn">
<button class="btn btn-default" ng-disabled="Cannot_Allocate_Yet" ng-click="Get_Sampling_Request_Details()" type="button">{{All_Labels.Common.Display}}</button>
</span>
</div>
and here is the scope function invoked upon clicking on the button:
$scope.Get_Sampling_Request_Details = function () {
console.log("$scope.aabbcc: " + $scope.aabbcc) ;
}
The variable $scope.aabbcc is initialized to 0 upon controller's loading.
Regardless what I type into the input element, I always get 0 in the console.

This scenario generally happens, If you have wrapped your HTML inside ng-if, ng-switch ng-repeat.. or some other directive that creates new child scope.
See this fiddle.
So it's a best practice to wrap your scope in some model to leverage protypical inheritance and correctly bind data to $scope.
Like : $scope.data.aabbcc = 0 and use it like ng-model ='data.aabbcc'.
See this for few minutes and Read this for complete understanding.

check this working example
<div ng-controller="MyCtrl">
Hello, {{name}}!
<input type="number" ng-model="name"/>
<button class="btn btn-default" ng-disabled="Cannot_Allocate_Yet" ng-
click="Get_Sampling_Request_Details()" type="button">test</button>
</div>
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.name = 0;
$scope.Get_Sampling_Request_Details = function () {
console.log("$scope.aabbcc: " + $scope.name) ;
}
}

AngularJS controllers control the data. The scope is the binding part between the HTML (view) and the JavaScript (controller). You must define the ng-model inside a ng-controller within which its scope lies. Try this out.
<div ng-controller="myCtrl">
<div class="input-group" style="width:100px">
<input type="number"
class="form-control"
id="Sampling_Request_for_Current_Sampling_INPUT"
ng-model="aabbcc"
style="width:125px;text-align:center">
<span class="input-group-btn">
<button class="btn btn-default" ng-disabled="Cannot_Allocate_Yet" ng-click="Get_Sampling_Request_Details()" type="button">{{All_Labels.Common.Display}}</button>
</span>
</div>
</div>
<script>
var app = angular.module('Myapp', []);
app.controller('myCtrl', function($scope) {
$scope.Get_Sampling_Request_Details = function () {
console.log("$scope.aabbcc: " + $scope.aabbcc) ;
}
});
</script>

Declare an empty object in your controller section .
eg: $scope.obj = {};
And use like ng-model="obj.key_name" in your html. It will work.

Related

Accessing second level scope from third level scope angular js

As illustrated above I'm trying to access the second level 2 scope from level 3 scope from angular controller
but, parent comes as null and it is able to access Level1 scope though which i dont want
Need too access level2 scope from level3
as you can see in below pic the level 2 scope from parent comes as
null
angular.element(...).scope() will get the scope(not current scope) which your target element belongs to.
In the below example, I have added four input(outside controllers, levelOne, levelTwo, levelThree) to make it clear(open console to confirm it).
angular.module("app", [])
.controller("levelOne", function($scope) {
$scope.data = 'levelOne';
})
.controller("levelTwo", function($scope) {
$scope.childData = 'levelTwo';
})
.controller("levelThree", function($scope) {
$scope.grandChildData = 'levelThree';
console.log($scope.$parent);
var scope = angular.element(document.getElementById("input")).scope();
var parentScope = angular.element(document.getElementById("levelOne")).scope();
var childScope = angular.element(document.getElementById("levelTwo")).scope();
var grandChildScope = angular.element(document.getElementById("levelThree")).scope();
console.log('scope', scope);
console.log('parentScope', parentScope);
console.log('childScope', childScope);
console.log('grandChildScope', grandChildScope);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="app">
<input id="input" type="text" value="not in controller">
<hr>
<div ng-controller="levelOne">
<input id="levelOne" type="text" ng-model="data">
<hr>
<div ng-controller="levelTwo">
<input id="levelTwo" type="text" ng-model="childData">
<hr>
<div ng-controller="levelThree">
<input id="levelThree" type="text" ng-model="grandChildData">
</div>
</div>
</div>
</div>
and based on your provided screenshot, maybe you are fitted to the second situation(element belongs to level1's template), then the solution should be moving the element into level3's template.

Cannot get value of ng-model through $scope

I am trying to get the value of the ng-model when clicking a button which triggers a function to add each ng-model value to an object. When trying to get the value of $scope.shipNameFirst, it comes up as undefined in the second example.
I've read that it's better to get the value of $scope on the view rather than passing it through the stripeBtn function, so ideally I'd like to do it that way. Hopefully this makes sense.
Can someone explain why this is not working?
Working
HTML
<input type="text" ng-model="shipNameFirst">
<input type="text" ng-model="shipNameLast">
<button type="button" ng-click="stripeBtn(shipNameFirst, shipNameLast)">Checkout with Stripe</button>
Controller
$scope.stripeBtn = function(shipNameFirst, shipNameLast){
$scope.details = {
recNameFirst: shipNameFirst,
recNameLast: shipNameLast,
}
}
Not Working
HTML
<input type="text" ng-model="shipNameFirst">
<input type="text" ng-model="shipNameLast">
<button type="button" ng-click="stripeBtn()">Checkout with Stripe</button>
Controller
$scope.stripeBtn = function(){
console.log($scope.shipNameFirst); //logging this (with $scope) comes up as undefined
$scope.details = {
recNameFirst: $scope.shipNameFirst,
recNameLast: $scope.shipNameLast,
}
}
Thanks!
Check the following code. It's working nicely.
var myApp = angular.module('myApp', []);
myApp.controller('myController', function($scope){
$scope.stripeBtn = function(){
console.log($scope.shipNameFirst);
$scope.details = {
recNameFirst: $scope.shipNameFirst,
recNameLast: $scope.shipNameLast,
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<input type="text" ng-model="shipNameFirst">
<input type="text" ng-model="shipNameLast">
<button type="button" ng-click="stripeBtn()">Checkout with Stripe</button>
</div>

angular js ng-hide in real time doesn't work

I have a snippet of html which I'd like to hide if a variable $scope.city is empty html:
<div class="col-lg-12" **ng-hide="{{city === ''}}"**>
<h1>{{forecast.data.city.country}} ,{{forecast.data.city.name}} </h1>
<h2>Forcast for : {{city}}</h2>
</div>
<div class="col-lg-8">
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">City#</span>
<input type="text" **ng-model="city"** class="form-control" placeholder="Username" aria-describedby=" basic-addon1">
</div>
</div>
even though they are bound the element does not hide in real time, only if I go to that page with already empty $scope.city variable , there is a one more variable city which comes from varService (I use it to share variable between multiple controllers) here is Angular Code:
app.controller('forecastController', ['$scope','varService','$http', function($scope,varService,$http){
$scope.$watch('city', function() {
varService.city = $scope.city;
});
$scope.city = varService.city;
$scope.numOfDays = 2;
$scope.days = 2;
$scope.$watchGroup(['days', 'city'], function() {
$http.get('http://api.openweathermap.org/data/2.5/forecast?q='+$scope.city+'&mode=json&appid=e652a2c384655ea24f5b12d2fb84c60f&cnt='+$scope.days+'&units=metric')
.then(function(data) { $scope.forecast = data; });
});
}]);
so how do I make ng-hide work in real time as my $scope.city changes ? Thanks.
Instead of
ng-hide="{{city === ''}}"
Write it like this
ng-hide="city.length===0"
city is already bound to $scope in your controller, and ng-hide/ng-show expects an expression. so you don't need to use the double curly brackets({{}}) to evaluate it to true or false, just provide the expression as as like so "city.length===0".
try this;
ng-hide="city == ''"
Change your code use ng-if instead of ng-hide, because ng-if does not create element
<div class="col-lg-12" ng-if="!city.length">
<h1>{{forecast.data.city.country}} ,{{forecast.data.city.name}} </h1>
<h2>Forcast for : {{city}}</h2>
</div>
OR
<div class="col-lg-12" ng-hide="city.length">
<h1>{{forecast.data.city.country}} ,{{forecast.data.city.name}} </h1>
<h2>Forcast for : {{city}}</h2>
</div>

Access "calling scope" and strange behaviour

I have a simple snippet of code :
function SomeCtrl($scope) {
$scope.modify = function(value) {
$scope.something = "Hello";
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="SomeCtrl">
<div ng-repeat="toto in [1,2,4,5]">
<input ng-model="something" />
<input ng-model="something" />
<button ng-click="modify()">Modify</button>
</div>
</div>
</div>
Does anyone can explain how I could change it so the modify() function only change the textfields inside the scope of the button I click ?
I also don't get why only the text fields which have not been edited are modified by the function.
Thank you very much
This is because ng-repeat creates it's own scope. Using prototypal inheritance. By declaring ng-model you're creating a new field on that new scope.
But this will work for what you're trying to do.
<div ng-repeat="toto in [1,2,4,5]" ng-init="something = {}">
<input ng-model="something.hi" />
<input ng-model="something.hi" />
<button ng-click="modify(something)">Modify</button>
</div>
</body>
.controller('ctrl', function ($scope) {
$scope.modify = function (something) {
something.hi = "hello";
}
})
In this case you are just pushing out on screen the same info for times, meanwhile binding everything to the same variable. You can just simply create array and bind every input line to appropriate array element. And by pressing "modify" button, pass parameter, witch array element must be changed.
function SomeCtrl($scope) {
$scope.something = [];
$scope.modify = function(toto) {
$scope.something[toto] = toto;
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="SomeCtrl">
<div ng-repeat="toto in [1,2,4,5]">
<input ng-model="something[toto]" />
<input ng-model="something[toto]" />
<button ng-click="modify(toto)">Modify</button>
</div>
</div>
</div>

How to get an element's attribute with AngularJS

I have the following code:
<div class="col-md-10" data-ng-controller="type-controller">
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-success" ng-model="typeId" data-btn-radio="'1'">
Option 1
</label>
<label class="btn btn-success" ng-model="typeId" data-btn-radio="'2'">
Option 2
</label>
</div>
<input data-ng-model="typeId" name="typeId" type="hidden" data-start="2" />
</div>
My type-controller is empty so I'm omitting it - but I want to get the value of the attribute data-start from the last input inside the type-controller.
I'm not using jQuery.
IF the attribute data-start is significant because it is being used by some other 3rd party library, then you might consider simply using ng-init when you create this on the server:
<input data-ng-model="typeId" name="typeId" type="hidden" data-start="2"
ng-init='start = 2' />
This will essentially run any code you need, and doesn't involve you having to parse out data attributes from the DOM.
You could write a pretty trivial directive to pull in the value and publish using an expression. This will essentially accomplish the same thing, but is more difficult in my opinion:
angular.module('data-pluck', [])
.controller('fooController', function() {
this.name = 'Foo Controller';
})
.directive('pluckData', ['$parse',
function($parse) {
return {
restrict: 'A',
link: function(scope, elem, attrs) {
var expression = function() {};
expression.assign = function() {};
scope.$watch(attrs.placeData, function() {
expression = $parse(attrs.placeData);
});
scope.$watch(attrs.pluckData, function() {
expression.assign(scope, attrs[attrs.pluckData]);
});
}
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='data-pluck' ng-controller='fooController as ctrl'>
<h1>{{ctrl.name}}</h1>
<div data-my-val="I'm value one" pluck-data='myVal' place-data='ctrl.valueOne'>
<p>I'm a regular old <code><p></code> tag</p>
<input type='hidden' data-my-val="I'm the second value" pluck-data='myVal' place-data='ctrl.valueTwo' />
</div>
<h3>These Values Populated Dynamically</h3>
<ul>
<li>ctrl.valueOne = {{ctrl.valueOne}}</li>
<li>ctrl.valueTwo = {{ctrl.valueTwo}}</li>
</ul>
</div>
Angular comes with jqLite built in, which still has the attr() function. But it's not the Angular "way" to be manually fiddling around in the DOM from a controller. Your scope should be the interface between them.
I'm curious as to why you have a value in an attribute in your UI that isn't defined first in your model / scope? How does this value get changed? Is there a reason why you can't set it in the controller:
$scope.start = 2;
and then:
<input data-ng-model="typeId" name="typeId" type="hidden" data-start="{{start}}" />
Can you explain a little about what data-start is meant to do?

Categories