Input field not being updated from controller in Angularjs - javascript

I am in learning phase of Angularjs and am stuck in a problem for last two days. I have seen lots of answer but don't know how to adapt those solutions in my case. What I want to do is update the input field via buttons using angularjs.
// html
<body ng-controller="Controller">
<input type="number" ng-model="data" update-view>
<br>
<label for="data">{{data}}</label>
<button name="btn1" ng-click='updateInput(1)'>1</button>
</body>
// js
var app = angular.module('calculator',[]);
app.controller('Controller', function($scope, $timeout){
$scope.data = 0;
var val = '';
$scope.updateInput = function(param) {
val += String(param);
$scope.data = val;
// val = param;
// $scope.data = val;
}
});
The expressions gets evaluated but the input field is not updating. I have seen other updating views with $setViewValue and $render but I don't know how to use them here.
app.directive('updateView', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
element.bind('change', function () {
// console.log(ngModel);
scope.$apply(setAnotherValue);
});
function setAnotherValue() {
ngModel.$setViewValue(scope.data);
ngModel.$render();
}
}
};
});
Any help would be appreciated. Thanks

You don't need a directive for updating.
You seem to be setting a string value to $scope.data, which throws an error, because the input type is number.
angular.module('calculator', [])
.controller('Controller', function($scope){
$scope.data = 0;
var val = '';
$scope.updateInput = function(n){
val = n;
$scope.data = val;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<body ng-app="calculator" ng-controller="Controller">
<input type="number" ng-model="data">
<button ng-click="updateInput(1)">1</button>
</body>

I was noting that without converting the parameter into string, the input field would update with the changed model but as soon as I would change it into String, it would not update the input field. Also there was error thrown in console. So I just, on hit and trial basis, converted it back to int by changing only one piece of line $scope.data = val; into $scope.data = parseInt(val, 10); and hurrrayyy the input field is all updating just like I wanted. And as #cither suggested, I don't need to directive for this. Following is my working code
var app = angular.module('calculator',[]);
app.controller('Controller', function($scope, $timeout){
$scope.data = 0;
var val = '';
$scope.updateInput = function(param) {
val += String(param);
$scope.data = parseInt(val, 10);
}
});

Related

AngularJS calling a controller in a directive

I am trying to follow from what I can tell so far is a pretty decent tutorial but I am a little stuck on a part where I need to create a directive to seperate a chunk of html and use a controller to generate the data.
var app = angular.module('newModule',[]);
app.directive('stateView', function(){
return{
restrict: 'E',
templateUrl: 'state-view.html',
controller: 'stateController',
controllerAs: 'stateCtrl'
}
});
app.controller('stateController',function(){
this.addStateTo = function(country){
if(!country.states){
country.states = [];
}
country.states.push({name: this.newState});
this.newState = "";
};
});
My HTML stateview looks like this (C is a value from another controller to itterate through a list of other objects).
<div>
<input type="text" name="state" ng-model="stateCtrl.newState">
<a href ng-click="stateCtrl.addStateTo(c)"> Add State {{ stateCtrl.newState }}</a>
</div>
and the only HTML referrence I have on my index is the following:
<state-view></state-view>
It looks clean, but the problem is that it does not reconize the function addStateTo unless I tell the DIV element that it is the ng-controller called StateController. Isn't this what the directive is telling the HTML attribute?
You are using the ControllerAs syntax and referencing the controller context appropriately (i.e. stateCtrl.newState and stateCtrl.addStateTo(c)). The problem is that you aren't creating the controller context properly. Your controller code should look like this:
app.controller('stateController', function() {
var vm = this;
this.addStateTo = function(country) {
if (!country.states) {
country.states = [];
}
country.states.push({
name: vm.newState
});
vm.newState = "";
};
});
Working example here
Try this instead ($scope instead of this):
app.controller('stateController',function($scope){
$scope.addStateTo = function(country){
if(!country.states){
country.states = [];
}
country.states.push({name: this.newState});
$scope.newState = "";
};
});
OR
app.controller('stateController',function(){
var vm = this;
vm.addStateTo = function(country){
if(!country.states){
country.states = [];
}
country.states.push({name: this.newState});
vm.newState = "";
};
});
Try adding bindto controller true in your directive. And also the above answer is correct in fixing other issues you may run into, i.e mapping your this to the function, though at present not doing that may not cause a problem.
var app = angular.module('newModule',[]);
app.directive('stateView', function(){
return{
restrict: 'E',
templateUrl: 'state-view.html',
controller: 'stateController',
controllerAs: 'stateCtrl',
bindToController: true
}
});
app.controller('stateController',function(){
var vm = this;
vm.addStateTo = function(country){
if(!country.states){
country.states = [];
}
country.states.push({name: vm.newState});
vm.newState = "";
};
});

how to bind a directive var to controller

i have a problem with using 2 way binding in angular, when i change my input, the change dosnt affect to controller. but the first init from controller affect directive.
in the picture i changed the value, but vm.date still have value test.
my directive:
(function (app) {
app.directive('datePicker', function () {
//Template
var template = function (element, attrs) {
htmltext =
'<input ng-readonly="true" type="text" id="' + attrs.elementId +
'" ng-model="' + attrs.model + '" type="date" />';
return htmltext;
}
//Manipulation
var link = function ($scope, elements, attrs, ctrls) {
//Declare variables we need
var el = '#' + attrs.elementId + '';
var m = attrs.model;
var jdate;
var date;
$scope[attrs.model] = [];
$(el).on('change', function (v) {
jdate = $(el).val();
gdate = moment(jdate, 'jYYYY/jMM/jDD').format('YYYY-MM-DD');
if (moment(gdate, 'YYYY-MM-DD', true).isValid()) {
date = new Date(gdate);
$scope[m][0] = date;
$scope[m][1] = jdate;
//console.log($scope[m]);
$scope.vm[m] = $scope[m];
console.log($scope.vm); //----> Here Console Write Right Data
} else {
//console.log('Oh, SomeThing is Wrong!');
}
});
} // end of link
return {
restrict: 'E',
scope: {vm: '='},
template: template,
link: link
};
});
}(angular.module('app')));
and my controller:
(function (app) {
app.controller('test', ['$scope', function ($scope) {
var vm = this;
vm.date = 'test';
vm.mydate = 'test2';
}]);
}(angular.module('app')));
and html:
<body ng-app="app">
<div ng-controller="test as vm">
<date-picker element-id="NN" model="vm.date" vm="vm"></date-picker>
<p>{{vm.date}}</p>
<date-picker element-id="NN2" model="vm.mydate" vm="vm"></date-picker>
<p>{{vm.mydate}}</p>
</div>
</body>
I am not sure why you made the textbox as readonly, but if you remove that readonly and try to update the textbox then the two way binding works. Here's the fiddle for that
https://fiddle.jshell.net/dzfe50om/
the answer:
Your controller has a date property, not a vm.date property. – zeroflagL May 25 at 13:48
You should define vm to $scope instead of this;
var vm = $scope;

Get input value in a variable in Angularjs before submit to call a webapi

I would like to access the input field value inside a variable that could be used in AngularJS so that I could add it to a string with the help of which I could call a rest api.
kindly help.
<body ng-app="myApp">
<div ng-controller="myCtr">
<form name="myForm">
<input type="text" ng-model='pinCode' id="zip" onBlur="myZipcode">
{{city}}
{{state}}
</form>
</div>
<script>
var zip;
var pat1;
function myZipcode(){
zip = document.getElementById("zip").value;
pat1 = 'http://ziptasticapi.com/'+zip;
}
var myApp = angular.module('myApp' , []);
myApp.controller('myCtr', function($scope, $http){
var path = 'http://ziptasticapi.com/12345'
$http.get(pat1).success(function (response) {
$scope.city = response.city;
$scope.state = response.state;});
});
</script>
</body>
Here in http.get service if I use path variable instead of pat1 it works.
Another thing that I want the state and city to come dynamically without the form to be submitted and to be called from an REST API. That is why I am trying to get the input value inside a variable to accomplish the task
No need to define extra var for pinCode because of you used ng-model so you can access pinCode from your controller. Also should use ng-blur instead of onBlur.
You can use like
HTML:
<input type="text" ng-model='pinCode' id="zip" ng-blur="myZipcode()">
Controller:
var myApp = angular.module('myApp' , []);
myApp.controller('myCtr', function($scope, $http){
$scope.pinCode= ''; // defaulr empty
var path = 'http://ziptasticapi.com/';
$scope. myZipcode = function() {
$http.get(path + $scope.pinCode).success(function (response) {
$scope.city = response.city;
$scope.state = response.state;
});
};
});
You should not access html elements from your controller code. Angular's two way data-binding already transfers the form input's value into the $scope.pinCode variable. So you only need some action to trigger your server call. See this sample in the angular docs: https://docs.angularjs.org/api/ng/directive/ngSubmit
myApp.controller('myCtr', function($scope, $http) {
$scope.doCall = function() {
// $scope.pinCode() is set here
$scope.$http.get(...).then(
function(response) {
$scope.city = response.data.city; // or similar
}
);
}
});
just bind zip and pat1 on controller's scope
Controller:
myApp.controller('myCtr', function($scope, $http){
$scope.zip = document.getElementById("zip").value || 0;
$scope. pat1 = 'http://ziptasticapi.com/'+ $scope.zip || '';
$scope.myZipcode();
});
and then in zipcode
Zipcode function:
$scope.myZipcode = function myZipcode(){
$scope,zip = document.getElementById("zip").value;
$scop.pat1 = 'http://ziptasticapi.com/'+zip;
$http.get(pat1).success(function (response) {
$scope.city = response.city;
$scope.state = response.state;}
}
Complete code:
<body ng-app="myApp">
<div ng-controller="myCtr">
<form name="myForm">
<input type="text" ng-model='pinCode' id="zip" ng-blur="myZipcode">
{{city}}
{{state}}
</form>
</div>
<script>
myApp.controller('myCtr', function($scope, $http){
$scope.zip = document.getElementById("zip").value || 0;
$scope. pat1 = 'http://ziptasticapi.com/'+ $scope.zip || '';
$scope.myZipcode();
$scope.myZipcode = function myZipcode(){
$scope,zip = document.getElementById("zip").value;
$scop.pat1 = 'http://ziptasticapi.com/'+zip;
$http.get(pat1).success(function (response) {
$scope.city = response.city;
$scope.state = response.state;}
}
});
</script>
</body>

Need help with simple angularjs programming

I am trying to do simple programming in angularjs. I have created two buttons. The first button has text "clickHere", and the second has no text. My task is when I click the button that has text, it will automatically get empty and the second button will have the same text. (and vice versa).
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.name = 'Superhero';
$scope.name1 = '';
var val = 'Hello';
$scope.click0 = function() {
//alert("hello!");
$scope.name = $scope.name1;
$scope.name1="";
//return val;
};
$scope.click1 = function() {
//alert("hello!");
$scope.name1 = $scope.name;
$scope.name="";
// return val;
};
}
<body ng-app="myApp">
<div ng-controller="MyCtrl">
<button ng-click="click0()" >{{name}}</button>
<button ng-click="click1()" >{{name1}}</button>
</div>
</body>
Here is my code in jsfiddle. http://jsfiddle.net/simpleorchid/a65zV/
I think your issue was you were overwriting your stored value. I added a $scope variable called word, and now it works:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.word = 'Superhero';
$scope.name = $scope.word;
$scope.name1 = '';
$scope.click0 = function() {
$scope.name1 = $scope.word;
$scope.name="";
};
$scope.click1 = function() {
$scope.name = $scope.word;
$scope.name1="";
};
}
Udpated Fiddle: http://jsfiddle.net/pWjLR/1/
Just replace the click1() with click0() like in the JSFiddle here and everything will work just as you want it to.

alternative method instead $watch in angularjs

I have a scope variable, when it returns true, i need to trigger some events or do something. I my case, the every first time, the scope variable returns undefined and later it returns true. In this case i used $watch method to get the expected funcionality. Is there any alternative approach to do the same instead using $watch ?
scope.$watch () ->
scope.initiateChild
, (value) ->
if value is true
$timeout ->
scope.buildOnboarding()
, 1000
You can try using AngularJS $on(), $emit() and $broadcast().
Here is an example: http://www.binaryintellect.net/articles/5d8be0b6-e294-457e-82b0-ba7cc10cae0e.aspx
You can use JavaScript getters and setters without any expense of using $watch.
Write code in the setter to do what you want when angular changes the your model's value you are using in scope. It gets null or an a State object as user types. Useful for working with type ahead text boxes that have dependencies on each other. Like list of counties after typing state without user selecting anything.
Here is some pseudo style code to get the idea.
<input ng-model="searchStuff.stateSearchText" />
<div>{{searchStuff.stateObject.counties.length}}</div>
<div>{{searchStuff.stateObject.population}}</div>
$scope.searchStuff=new function(){var me=this;};
$scope.searchStuff.stateObject = null;
$scope.searchStuff.getStateObjectFromSearchText = function(search){
// get set object from search then
return stateObject;
};
$scope.searchStuff._stateSearchText= "";
Object.defineProperty($scope.searchStuff, 'stateSearchText', {
get: function () {
return me._stateSearchText;
},
set: function (value) {
me,_stateSearchText = value;
me.stateObject = getStateObjectFromSearchText (value);
}
});
See this fiddle: http://jsfiddle.net/simpulton/XqDxG/
Also watch the following video: Communicating Between Controllers
A sample example is given below
Html:
<div ng-controller="ControllerZero">
<input ng-model="message" >
<button ng-click="handleClick(message);">LOG</button>
</div>
<div ng-controller="ControllerOne">
<input ng-model="message" >
</div>
<div ng-controller="ControllerTwo">
<input ng-model="message" >
</div>
javascript:
var myModule = angular.module('myModule', []);
myModule.factory('mySharedService', function($rootScope) {
var sharedService = {};
sharedService.message = '';
sharedService.prepForBroadcast = function(msg) {
this.message = msg;
this.broadcastItem();
};
sharedService.broadcastItem = function() {
$rootScope.$broadcast('handleBroadcast');
};
return sharedService;
});
function ControllerZero($scope, sharedService) {
$scope.handleClick = function(msg) {
sharedService.prepForBroadcast(msg);
};
$scope.$on('handleBroadcast', function() {
$scope.message = sharedService.message;
});
}
function ControllerOne($scope, sharedService) {
$scope.$on('handleBroadcast', function() {
$scope.message = 'ONE: ' + sharedService.message;
});
}
function ControllerTwo($scope, sharedService) {
$scope.$on('handleBroadcast', function() {
$scope.message = 'TWO: ' + sharedService.message;
});
}
ControllerZero.$inject = ['$scope', 'mySharedService'];
ControllerOne.$inject = ['$scope', 'mySharedService'];
ControllerTwo.$inject = ['$scope', 'mySharedService'];

Categories

Resources