angularjs: not able to pass a variable value from controller to view - angularjs

(function() {
angular
.module('myApp.home', [])
.factory('myService', function($http) {
return {
getInfo: function() {
// return something
}
};
})
.controller('HomeController', function($scope, $routeParams, myService) {
var my = this;
var sid;
myService.getInfo().success(function(data) {
my.id = data.id;
//sid= my.id;
});
//my.id = sid;
});
})();
I'm trying to access the variable id in my view. But I'm not able to do so. I'm getting an undefined variable error.
I even tried to declare a variable sid globally so that it can be accessed from everywhere and I tried assigning value to it as well but that effort also didn't bring up any results.
My services are working fine and they are returning data. I'm trying to use the id in my view but don't know where I messed it up.
Any help?
EDIT
And my HTML is like this:
<div data-id="my.id"></div>

If you want to use it in your view you have to bind it to a scope e.g. $scope.id - check this link for reference.

Below is your html, how it should be.
<div ng-app="app" ng-controller="HomeController as home">
<div data-id="home.id">{{home.id}}</div>
</div>
Below is how your controller part.
angular.module('app', [])
.controller('HomeController', function () {
this.id = "someValue";
});
http://jsfiddle.net/grdmLfxt/

use controllerAs : vm then you can access vm.id in your view.
HTML
<div ng-app="app" ng-controller="HomeController as vm">
<div data-id="vm.id">{{vm.id}}</div>
</div>
Controller
.controller('HomeController', function () {
var vm = this;
vm.id = "someValue";
});
for more info read this

small change in javascript code and html. try this.
Javascript
(function() {
angular
.module('myApp.home', [])
.factory('myService', function($http) {
return {
getInfo: function() {
// return something
}
};
})
.controller('HomeController', function($scope, $routeParams, myService) {
var my = this;
var sid;
myService.getInfo().success(function(data) {
$scope.id = data.id; // changed from my.id to $scope.id
//sid= my.id;
});
//my.id = sid;
});
})();
HTML
<div data-id="id"></div>

Related

How to get data from json to view in AngularJS

I have an Angular controller that gets data via a service from 2 different json files, and I need to pass that data to a view.
The controller file:
.controller('MainController', ['info', function (info){
var vm = this;
info.getAddresses().then(function(data) {
vm.addresses = data.addresses;
});
info.getNames().then(function(data) {
vm.names = data.names;
});
console.log(this);
}])
The getAddresses and getNames functions are just $.get('json-url').
If I use console.log(this) in the controller just before the closing bracket, I can see in the console the data below:
but I cannot access that 2 properties from the view. Am I missing something?
It's probably a digest cycle issue. Adding $scope.$apply would fix the issue.
$.get() from jQuery alter the value of vm.names but it's not part of the Angular digest cycle.
Here is a working example, hope this helps
angular.module('myApp', [])
.factory('info', function() {
var mock = function() {
return new Promise(function(resolve, reject) {
resolve({
"names": ['Alice', 'Bob']
});
});
};
return {
getNames: mock
};
})
.controller('MainController', function(info,$scope) {
var vm = this;
info.getNames().then(function(data) {
vm.names = data.names;
// trigger $apply manually
$scope.$apply();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MainController as vm">
{{vm.names}}
</div>
</div>
use scope variable to store the data instead of var
.controller('MainController', ['info', '$scope', $scope, function (info){
$scope.vm = this;
info.getAddresses().then(function(data) {
$scope.vm.addresses = data.addresses;
});
info.getNames().then(function(data) {
$scope.vm.names = data.names;
});
console.log(this);
}])
and call this scope variable in your view like
<tr ng-repeat = item in vm>
<td>you can get your data here</td>
</tr>
Hope this works
You are assigning your data to a variable and not to the $scope.
Your controller should be like this
.controller('MainController', ['info', '$scope', function (info, $scope){
info.getAddresses().then(function(data) {
$scope.addresses = data.addresses;
});
info.getNames().then(function(data) {
$scope.names = data.names;
});
console.log($scope);
}])
Here you have used controller as syntax. So you need to use it into ng-controller. Check below code.
<div ng-controller="MainController as vm">
<div ng-repeat="vm.addresses in address">{{ address }}</div>
<div ng-repeat="vm.names in name">{{ name}}</div>
</div>
If address or name is json object then you need to use specific key within address or name object.
For Angular 2+
Hold the json response in some variable:
public data:any=your json response;
And then in view, display it vi using *ngFor directive:
<p *ngFor="let d of data">{{d}}</p>

Need help to understand async calls in angular js

I have a main controller and nested controllers within it. In the main controller I have defined object by async query to the service, and try to use the object in the nested controller. But in the object in the nested controller is empty, cause it fires before it will be updated in the main controller.
As I understand, asyncronous query should updates the scope after data obtain?
.controller('MainController', ['$scope', function($scope) {
$scope.uData = {};
$scope.uDataCurrent = {};
$scope.usersData = usersFactory.getUsersData().query(
function(response) {
$scope.uData = response;
$scope.uDataCurrent = $filter('filter')($scope.uData, {'user':$scope.myuser});
$scope.uDataCurrent = $scope.uDataCurrent[0];
},
function(response) {
$scope.message = "Error: "+response.status + " " + response.statusText;
});
})]
.controller('NestedController', ['$scope', function($scope) {
console.log($scope.uDataCurrent); // returns empty object
}])
Service:
.service('usersFactory', ['$resource', 'baseURL', function($resource,baseURL) {
this.getUsersData = function(){
return $resource(baseURL+"/index.php?app=users&format=raw&resource=user",null, {'update':{method:'PUT' }});
};
}])
You could use $scope.$watch.
angular.module("App", [])
.controller("OuterCtrl", ["$scope", "$timeout", function($scope, $timeout) {
$scope.users = null;
$timeout(function() {
$scope.users = ["John", "Jack"];
}, 500);
}]).controller("InnerCtrl", ["$scope", function($scope) {
$scope.changeCount = 0;
// TODO: Bad practice to rely on outer scopes here as its not enforced
// to have an OuterCtrl scope as parent scope. In this example every
// occurrences of InnerCtrl is embedded in an OuterCtrl in the html
$scope.$watch("users", function(newValue, oldValue) {
// This code runs when the users array is changed
$scope.changeCount++;
});
}]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.js"></script>
<div ng-app="App">
<div ng-controller="OuterCtrl">
<div ng-controller="InnerCtrl">
<div>Change count: {{changeCount}}</div>
<div>Users</div>
<div ng-hide="users"> Loading...</div>
<ul>
<li ng-repeat="name in users">{{name}}</li>
</ul>
</div>
</div>
</div>

How to access a variable in a controller function?

I'd like to be able to access a controller variable inside a function of this controller.
Why is the following code throwing an error into the console instead of showing the input value ?
JS:
var app = angular.module("app", []);
app.controller("TestCtrl", function($scope) {
$scope.string = "";
$scope.click = function() { // I've also tried with $scope in parameter
console.debug(string); // and $scope.string here, same issue
}
});
HTML :
<div ng-app="app" ng-controller="TestCtrl">
<input type="text" ng-model="string"></input>
<button ng-click="click()">Click me !</button>
</div>
JSFiddle
remove $scope from the argument in you click function, and use it inside the function - see below and updated fiddle
app.controller("TestCtrl", function($scope) {
$scope.string = "";
$scope.click = function() {
console.debug($scope.string);
}
});
You can try another approach:
app.controller("TestCtrl", function($scope) {
this.string = "";
var that = this;
$scope.click = function() {
console.debug(that.string);
}
});
See on JSFiddle:
http://jsfiddle.net/qn47syd2/

AngularJs asynchronous data binding

I'm very new to AngularJs and I have simple question. I want to put the name. But this name has one value at first but after 0.3-0.5 sec it have other value. I don't know how to bind it, that the value could change.
HTML code:
<div ng-controller="FormController">
<h2 >
{{getName()}}<br>
<span class="icon-f-gear"></span>
<small>Procesas</small>
</h2>
</div>
Angular controller:
var App = angular.module('form', ['ui.bootstrap']);
App.controller('FormController', ['$scope' ,'$http', function($scope, $http) {
$scope.tasks = [];
$scope.socket.stomp.subscribe("/app/tasks", function (message) {
if ($scope.tasks.length !=0){
$scope.tasks.removeAll();
}
JSON.parse(message.body).forEach(function (el) {
$scope.tasks.push(el);
});
});
$scope.getName = function(){
return $scope.tasks[0].form.name;
};
I'm using Stomp protocol, it gives me data not instantly, because it has to send request to server and get it back, it takes time. I tried to debug after the request variable $scope.tasks[0].form.name changes from undefined to "Institution", but in the screen undefined stays, how to bind variable to change the value dinamically. Thanks for help in advance!
UPDATE
Problem solved, I just had to use $scope.apply(...) function. Code here:
var App = angular.module('form', ['ui.bootstrap']);
App.controller('FormController', ['$scope' ,'$http', function($scope, $http) {
$scope.tasks = [];
$scope.socket.stomp.subscribe("/app/tasks", function (message) {
if ($scope.tasks.length !=0){
$scope.tasks.removeAll();
}
JSON.parse(message.body).forEach(function (el) {
$scope.tasks.push(el);
});
$scope.apply(function(){$scope.tasks});
});
$scope.getName = function(){
return $scope.tasks[0].form.name;
};
Thanks for help!
Most probably the subscribe callback is not being called in angular context. Try to wrap the callback code in $scope.$apply and see if it works
$scope.socket.stomp.subscribe("/app/tasks", function (message) {
$scope.$apply(function() {
if ($scope.tasks.length !=0){
$scope.tasks.removeAll();
}
JSON.parse(message.body).forEach(function (el) {
$scope.tasks.push(el);
});
});
});
I believe the method you are calling returns undefined, because it has no data.
In other words: give it an initial value, and it should work
I would rewrite it to:
<div ng-controller="FormController">
<h2>
{{formName}}<br>
<span class="icon-f-gear"></span>
<small>Procesas</small>
</h2>
</div>
And
App.controller('FormController', ['$scope' ,'$http', function($scope, $http) {
$scope.formName = '';
--- rest of code
Or, if you wish to keep it in the current way:
App.controller('FormController', ['$scope' ,'$http', function($scope, $http) {
$scope.tasks = [];
$scope.tasks[0].form.name = '';
or
$scope.getName = function(){
return ($scope.tasks.length > 0) ? $scope.tasks[0].form.name : '';
};
I hope this helps

updating $scope of controller A from controller B

var myApp = angular.module('myApp', []);
myApp.factory('Data', function() {
return {message: "I'm data from a service"}
})
function FirstCtrl($scope, Data){
$scope.data = Data;
}
function SecondCtrl($scope, Data){
//I want to send a string to the service so that the view associated with FirstCtrl is updated.
}
Ok, lets take this code for example. How would one set the message string from inside SecondCtrl so that the view binded with FirstCtrl is updated?
You may share data between controllers using a service (factory), but you will not use $scope directly.
Please refer to this video for a demonstration:
https://egghead.io/lessons/angularjs-sharing-data-between-controllers
Thumbs up for egghead \o/
Edit:
var myApp = angular.module('myApp', []);
myApp.factory('Data', function() {
return {message: "I'm data from a service"}
})
function FirstCtrl($scope, Data){
$scope.data = Data;
}
function SecondCtrl($scope, Data){
$scope.data = Data;
// Simply set the message or bind it to an input on your view:
$scope.data.message = 'new value'
}
Here is a demo: http://jsfiddle.net/suhvtr5r/
If this doesn´t work, please share your views with us
One thing you can do is to create another parent controller like this,and put common things to both controllers
<div ng-controller="parentController">
<div ng-Controller="pageOneController">
<input placeholder="{{placeholder}}" type="text" />
</div>
<div ng-Controller="pageTwoController">
<--other html-->
</div>
</div>
app.controller('parentController', ['$scope', function($scope) {
$scope.placeholder = "this is common to both child controllers";
}]);
If you want to do that you need getter and setter in your service here is the fiddle that do the trick for you :
HTML:
<div ng-app="myApp">
<div ng-controller="FirstCtrl">my first cotroller : {{data.message}}</div>
<div ng-controller="SecondCtrl">my second controller :
<input type="text" ng-model="data.message" ng-change="update()">
</div>
</div>
Angular:
var myApp = angular.module('myApp', []);
myApp.factory('Data', function () {
return {
message: '',
get: function () {
alert("DasdaS");
return this.message;
},
set: function (secondCtrlStr) {
this.message = secondCtrlStr;
}
};
})
function FirstCtrl($scope, Data) {
$scope.data = Data;
}
function SecondCtrl($scope, Data) {
$scope.update = function () {
Data.set($scope.data.message);
};
}

Resources