How to access a variable in a controller function? - angularjs

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/

Related

How to call a method from a controller to another controller in angular js

I have a view for SidebarController like below -
<a ng-click="reachMe($event);$event.preventDefault()" ng-href="#/app/hello">
Before going to the link I want to call reachMe() to check some changes on page and need to show an alert if any changes made
function SidebarController($rootScope, $scope, $state, $location, SidebarLoader){
$scope.reachMe = function(event){
//here I want to call function isPageChanged() from StaticPageController
//something like this
// if StaticPageController.isPageChanged() return true
// then show alert
// else
// $location.url($href)
}
}
Update 1 :
Not sure about this, But give it a try.
<div ng-app="testApp" ng-controller="ControllerOne">
<button ng-click="methodA();"> Call Another Controller</button>
</div>
<script>
var app = angular.module('testApp', []);
app.controller('ControllerOne', function($scope, $rootScope) {
$scope.reachMe = function() {
var arrayData = [1,2,3];
$rootScope.$emit('callEvent', arrayData);
if($rootScope.isChanged){
// Show Alert
}else{
//Go to route
}
}
});
app.controller('ControllerTwo', function($scope, $rootScope,$state) {
$scope.checkSomethingChanged = function() {
alert("Hello");
$rootScope.isChanged = true;
}
$rootScope.$on('callEvent', function(event, data) {
console.log(data);
$scope.checkSomethingChanged();
});
});
Following method worked for me perfectly :
<div ng-app="testApp" ng-controller="ControllerOne">
<button ng-click="methodA();"> Call Another Controller</button>
</div>
<script>
var app = angular.module('testApp', []);
app.controller('ControllerOne', function($scope, $rootScope) {
$scope.methodA = function() {
var arrayData = [1,2,3];
$rootScope.$emit('callEvent', arrayData);
}
});
app.controller('ControllerTwo', function($scope, $rootScope) {
$scope.reachMe = function() {
alert("Hello");
}
$rootScope.$on('callEvent', function(event, data) {
console.log(data);
$scope.reachMe();
});
});
</script>
A controller is not the right concept for sharing functionality. Use a Factory or Service for that.
var logicFactory = function () {
return {
methodA: function () {
},
methodB: function()
{
}
};
}
You can then inject that factory into each controller where it is needed like:
var ControllerA = function ($scope,logicFactory) {
$scope.logic = logicFactory;
}
ControllerA.$inject = ['$scope', 'logicFactory'];
Another option is to use the broadcast/emit Patern. But I would use that only where really necessary:
Usage of $broadcast(), $emit() And $on() in AngularJS

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

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

AngularJS Factory functions that interact with each other

I have an AngularJS Factory that is an upload, I'm trying to make the progress fire a function called progressState but it's not working.
Is there anyway of getting this to work?
myApp.factory('fooFactory', function() {
return {
upload: function(foo){
upload(foo)
.progress(evt){
progressState(evt, state);
}
},
progressState: function(evt, state){
return fooVar;
}
};
});
use this
outside return
var self = this;
inside return
self.progressState(evt, state);
I have mocked up the best I can without access to your upload function, does this help
var myApp = angular.module('myApp', []);
myApp.factory('fooFactory', function() {
var factory = {};
factory.upload = function(foo){
console.log ('factory : ' , factory)
factory.progressState();
}
factory.progressState = function(){
console.log('progress state called')
}
return factory;
});
myApp.controller('myCtrl', ['$scope', 'fooFactory', function($scope, fooFactory){
$scope.test = 'controller active';
fooFactory.upload();
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myCtrl">
<p>{{test}}</p>
</div>
</div>

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