To pass a javascript variable to ng-click - angularjs

My example:
<button ng-click="action()" >Hello World</button>
Status : <span >{{foo}}</span>
<script>
var status= Math.random()*1000;
</script>
I want to pass a javascript variable status to action(). Is this possible?
function Mycontroller($scope,$window){
var status = $window.status//works
$scope.action = function($window){
//$window -is undefined;
//var status = $window.status
debugger
$scope.foo='default value for foo' + status;
}
}
Example 2:
window.status= Math.random()*1000;
<button ng-click="action(window.status)" >Hello World</button>
$scope.action = function($status){
// $status - is undefined ...Why??
}
Thank you very much.

No, it's not possible. Expressions use variables that are exposed on the scope. They can't access global variables (i.e. attributes of window), unless of course the window itself is exposed on the scope (using action(window.status), provided you have called $scope.window = $window before).

As JB Nizet said, you cant access the window or other global variables directly in an expression (like the one inside ng-click), only the scope. So window will return undefined in an expression. But, as HarishR said, you can access window in your controller, or a controller method, as his code shows.
But, if you really want to set it and pass it from the view, you can do an ng-init.
<div ng-controller="myController" ng-init="status = 1000">
<button ng-click="action(status)">Hello World</button>
Status : <span>{{foo}}</span>
</div>
see plunker: http://plnkr.co/edit/OWsLjAlLB4II2jGaKupN?p=preview
note that u cant access Math in the ng-init expression, as its a global variable but not on the scope.

try below
$scope.action = function(){
var status = $window.status
}
you dont need to receive $window in $scope.action...
why are you getting it as undefined is because, you are not passing it from HTML
<button ng-click="action()" >Hello World</button>
and actually you dont need to pass it from html and you are trying to receive it in your controller...

Related

Controller without $scope

I just come across some code where no $scope was there in the controller.
Here is the code
<div ng-app="myApp" ng-controller="ctrlCarLists as cars">
<button ng-click="cars.showCars()">
Cars
</button>
<button ng-click="alert(cars.data)">
Test
</button>
</div>
var app = angular.module('myApp', []);
app.controller("ctrlCarLists", function () {
this.data = 'hello';
this.showCars = function () {
alert("Ford, Toyata, Mercedes");
};
});
The above code is running, but this.data is not accessible...why? showCars() is accessible when the button is clicked. Why isn't this.data is not accessible?
What should be called when we declare any variable or function inside controller with the this keyword? Will it behave like a static property or function of a class?
jsfiddle link https://jsfiddle.net/tridip/z5wkzc0g/
ng-controller="ctrlCarLists as cars"
"cars" is referring to your controller, and "this" is refering to your controller as well.
ng-click="cars.showCars()"
When this function is triggered, it will refer to "showCars()" function in your controller.
As Yury Tarabanko has explained in his comment, alert function is not found, reason is:
https://docs.angularjs.org/guide/expression#context
Angular does not use JavaScript's eval() to evaluate expressions.
Instead Angular's $parse service processes these expressions.
Angular expressions do not have access to global variables like
window, document or location. This restriction is intentional. It
prevents accidental access to the global state – a common source of
subtle bugs.
Instead use services like $window and $location in functions called
from expressions. Such services provide mockable access to globals.
Source:
Why is ng-click not working?
ng-click requires an expression (see docs).
alert(cars.data)
is not an expression that angularJS can compile (it doesn't know what alert refers to) thus it should be replaced with
ng-click="cars.data()"
because cars.data() is an expression it can compile.
Fiddle
Or, alternatively
Fiddle
where we could have this:
this.alert = function (text) {
alert(text);
}

How to call a function defined in the controller inside of the view?

I know I can display a scope variable value by doing:
<div> This is my var value: {{myVar}} </div>
Suppose I have this function
$scope.displayVal = function(){
return myVar+5;
};
Is there a way to call it in a similar way?
<div>{{displayVal()}}</div>
or
<div ng-bind="displayVal()"></div>
If you use Controller as syntax
<div ng-controller="YourController as vm">
<div>{{vm.displayVal()}}</div>
</div>
It can be used directly like a function:
<div>{{displayVal()}}</div>
If you are initializing some values and want to call on page load then
<div ng-init="displayVal()"></div>
Since your function is declared in the scope, you can call it normally in (what I assume is) your view; for example:
// code in the controller
$scope.myVar = 10;
$scope.displayVal = function(){
return myVar + 5;
};
// code in the view
<input type="text" ng-model="displayVal()" /> // 15 will appear in the box
You can also call the function within a button; as to where the value will appear, I'll leave it to you:
<input type="button" value="Display Value" ng-click="displayVal()" />
On a side note this is how you would create the function:
$scope.displayVal = function displayVal(){
return myVar+5;
};
After the key word function you would need to enter the name of the function.

Why does not work ng-controller in HTML from AJAX?

I have HTML code that is returned from AJAX:
<div ng-controller="CounterPostsController">
<span ng-click="Do();"></span>
</div>
So, event ng-click does not work
In your CounterPostsController, do you have the Do() method defined and associated to the $scope variable?
i.e. $scope.Do() = function () {} or $scope.Do() = myCustomFunction;
You will need to associate your function to $scope in order the code above to work.
Hope this helps

A controller scope variable passed from function invoked in a template does not change the original controller variable when the parameter is changed

I have a scope variable, $scope.test. If I pass this variable in a function that is invoked in a template as an argument and then I try to change it in the controller, it seems that the original $scope.test does not change. Only the local variable, foo changes. But isn't foo a reference to $scope.test?
var mod = angular.module('app', []);
mod.controller('myCtrl', function($scope) {
$scope.test = 'test';
$scope.doSomething = function(foo) {
foo = 'scope.test should change';
}
})
Here, I'm passing test to the doSomething function which is in the controller above.
<body ng-app='app'>
<div ng-controller='myCtrl'>
<button ng-click="doSomething(test)">testing</button>
<h1>{{test}}</h1>
</div>
</body>
Here's the plunker: http://plnkr.co/edit/JBsos0qVJP47WgfD9Fee?p=preview
This is indeed something that you might want to do within Angular.js. However, in your case, you are passing a primitive string, which is passed by value instead of by reference in JavaScript. You can pass objects and change the properties of the objects, but when you pass primitives, they are not mutable. This is also a reason why one of the best practices for Angular.js is that any bindable items have a ., which is automatically a property of an object.
http://docstore.mik.ua/orelly/webprog/jscript/ch11_02.htm

Angular binding model in scope issue?

Hi I am new to the angular js and trying to write the chat application using the socket io and angular js with ionic for android platform. But in my chat page there is one issue.
I am trying to bind the textbox to the $scope.message variable using ng-model but it is not getting bind as the test when i show the same variable value in page itself it works as it is but in controller i gets value as undefined or empty
index.html
<body ng-app="farmApp" ng-controller="farmAppController" >
<ion-content>
<ul id="Messeges">
<li class="right">Welcome to Chat</li>
<li ng-repeat="chatMessage in messages">
{{chatMessage}}
</li>
</ul>
<form ng-submit="sendMessage()">
<input placeholder="Your message" ng-model="message">
<input type="submit" name="send" id="send" value="Send" class="btn btn-success">
<br/>
{{message}} //This updates the value as i type in textbox
</form>
</ion-content>
</body>
but when i see print that model on console it shows undefined when i define at the start in controller then it shows empty value
Controller.js
var farmAppControllers = angular.module('farmAppControllers',[]);
farmAppControllers.controller('farmAppController',['$scope','socket',function($scope,socket){
$scope.messages = [];
$scope.message = ''; //When i don't declare then console shows undefined on sendMessage function if declared then empty
socket.on("update", function (data) {
console.log(data);
$scope.messages.push(data);
});
$scope.sendMessage = function (){
console.log($scope);
console.log($scope.message); // This shows undefined or empty on console
socket.emit("msg",$scope.message);
$scope.messages.push($scope.message);
$scope.message ='';
};
}]);
My app.js
'use strict';
var farmApp = angular.module('farmApp', ['farmAppControllers','farmAppServices','ionic']);
And services.js for socket wrapper
var farmAppServices = angular.module('farmAppServices',[]);
farmAppServices.factory("socket",function($rootScope){
var socket = io.connect();
return {
on:function (eventName,callBack){
socket.on(eventName,function(){
var args = arguments;
$rootScope.$apply(function(){
callBack.apply(socket,args);
});
});
},
emit:function(eventName,data,callBack){
socket.emit(eventName,data,function(){
var args = arguments;
$rootScope.$apply(function(){
if(callBack){
callBack.apply(socket,args);
}
});
});
}
};
});
i stuck here... i try to google it but not able to solve it. In case of confusion feel free to comment. Any help would be great.
UPDATE
When i used the first answer of this question the problem got solved but still not clear why ng-submit is not working ? Any Idea Why ? Because it seems i am still unable to update the view scope from the controller ?
I think the problem is <ion-content> which is a directive and seems to create its own scope. From the docs:
Be aware that this directive gets its own child scope. If you do not understand why this is important, you can read https://docs.angularjs.org/guide/scope.
Therefore your message property isn't in the scope of your controller.
Objects are passed by reference and sendMessage is a function respectively an object, thats why it's still called correctly from the child scope.
What you should do is create an object with a name that makes sense to "package" the properties you want to share.
$scope.package = {}
$scope.package.messages = [];
$scope.package.message = 'You default message...';
And then in your function:
$scope.package.messages.push($scope.package.message);
And in your template:
<input placeholder="Your message" ng-model="package.message">
Here is a plunker with a working solution. It throws some random errors, I actually don't know ionic. But the example works and everything else doesn't matter.

Resources