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.
Related
I am really new to AngularJS. I want to pass some object from View (HTML) to my controller (JS).
Actually my Client will send me data in HTML and I have to take that data and process that data in my controller and then display the processed output on screen. He will be using some back-end technology called ServiceNow - https://www.servicenow.com/ .
All the solutions I saw had some event like click event or change event, but in my case this has to be done on page load.
I m using Input type hidden for passing the data to the controller, seems like it's not working.
So is there any other way I can do this ?
Here's the code I am trying to use
<div ng-controller="progressController" >
<input type="hidden" value="ABCD" ng-model="testingmodel.testing">
</div>
app.controller('progressController', function($scope) {
console.log($scope.testingmodel.testing);
});
It says undefined when I console.log my variable in Controller.
You're doing console.log(...) too early. At this time your controller doesn't have any information from the view.
The second problem is that you're binding the view to a variable in controller and not the other way around. Your $scope.testingmodel.testing is undefined and it will obviously the value in the view to undefined.
Solution
Use ng-init to initialize the model and the controller's hook $postLink to get the value after everything has been initialized.
Like this
<div ng-controller="progressController" >
<input type="hidden" ng-model="testingmodel.testing" ng-init="testingmodel.testing = 'ABCD'">
</div>
app.controller('progressController', function($scope) {
var $ctrl = this;
$ctrl.$postLink = function() {
console.log($scope.testingmodel.testing);
};
});
Edit: extra tip
I don't recomment using $scope for storing data since it makes the migration to newer angular more difficult.
Use controller instead.
Something like this:
<div ng-controller="progressController as $ctrl" >
<input type="hidden" ng-model="$ctrl.testingmodel.testing" ng-init="$ctrl.testingmodel.testing = 'ABCD'">
</div>
app.controller('progressController', function() {
var $ctrl = this;
$ctrl.$postLink = function() {
console.log($ctrl.testingmodel.testing);
};
});
You should use the ng-change or $watch
<div ng-controller="progressController" >
<input type="hidden" value="ABCD" ng-model="testingmodel.testing" ng-change="change()">
</div>
app.controller('progressController', function($scope) {
$scope.change = function(){
console.log($scope.testingmodel.testing);
}
});
Or:
app.controller('progressController', function($scope) {
$scope.$watch('testingmodel.testing', function(newValue, olValue){
console.log(newValue);
}
});
If you use ng-change, the function is only called if the user changes the value in UI.
If you use $watch anyway, the function is called.
You can't use value attribute for set or get value of any control, angularJS use ngModel for set or get values.
Here You should try like this way
app.controller('progressController', function($scope) {
//from here you can set value of your input
$scope.setValue = function(){
$scope.testingmodel = {}
$scope.testingmodel.testing = 'ABCD';
}
//From here you can get you value
$scope.getValue = function(){
console.log($scope.testingmodel.testing);
}
});
if you want to bind from html side then you should try like below
<input type="text" ng-model="testingmodel.testing">
<input type="hidden" ng-model="testingmodel.testing">
I have a form with a submit button which works fine. However I need to clear the form data from a clear button which is sitting outside the form on top right of the page. The clear button exist in a parent controller and sits above the form in top right header. The form sent from the clear button always comes up as undefined, which is because the clear button is not part of the form.
How do I pass the same instance of the form to clear? How do I clear the data? If this is a design issue I still need a workaround.
Here is a fiddle I have created to mimic that. Any help will be appreciated.
https://jsfiddle.net/SobDan/vj67rtb2/
<div ng-app>
<div class="col-md-10">
<h2>Todo</h2></div>
<div class="col-md-2">
<button class="btn pull-right" ng-click="clear(TodoForm)"> Close</button>
</div>
<br>
<div ng-controller="TodoCtrl">
<form name="TodoForm" ng-submit="addTodo()" name="testForm">
<input type="text" ng-model="todoText" size="30" placeholder="add new todo here">
<input class="btn-primary" type="submit" value="add">
</form>
</div>
function MainCtrl($scope) {
$scope.clear = function(form) {
alert(form); // the form is undefined
if (form.$dirty)
form.setPristine(); // clean this form
else
alert("form not dirty");
};
};
function TodoCtrl($scope) {
$scope.todoText = "test";
$scope.addTodo = function() {
alert("Submitted");
$scope.todoText = "";
// submit logic works fine
};
}
You should use $broadcast to communicate between controllers rather than trying to access the form which is outside scope.
Here is the fiddle and the explanation below
$broadcast function is used to broadcast events to all child $scope. Any interested child $scope can register to listen for the event using $on function. This functionality is used to communicate between controllers.
In your case, we signal to clear the form by broadcasting an event called clearForm from $rootScope. The TodoCtrl $scope listening on the event clearForm will receive a signal to clear form fields.
app.controller("MainCtrl", function($scope, $rootScope) {
$scope.clear = function(form) {
$rootScope.$broadcast("clearForm");
};
});
app.controller("TodoCtrl", function($scope) {
$scope.$on("clearForm", function() {
if ($scope.testForm.$dirty) {
$scope.testForm.$setPristine();
$scope.todoText = "";
} else {
alert("form not dirty");
}
});
});
AngularJS 1.1.x +
$scope.form.$setPristine() is only available from AngularJS version 1.1.x.
$setPristine() will only set the form status to pristine and will not clear the form field. You need to manually clear it by nullifying the $scope variables which will be reflected on the screen.
if ($scope.testForm.$dirty) {
$scope.testForm.$setPristine();
$scope.todoText = "";
}
AngularJS 1.0.x +
$setPristine function is not available in 1.0.x version.
The example Fiddle in your question seem to be configured to 1.0.x
In 1.0.x you simply clear the $scope variables
$scope.$on("clearForm", function() {
$scope.todoText = "";
});
see 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");
};
});
i am new in angular so not being able to understand when people do not like to have $scope in controller. so please tell me or show me few scenario with example when people create controller without scope.
what is the meaning of this ctrlCarLists as cars ?
many people may say by this code ctrlCarLists as cars we are creating instance of controller to access property of controller but when we use $scope then controller instance is created too.
please help me to understand..
thanks
This is known as the 'controller as' pattern. For more info, check this and this link.
You can refer the this to a variable, just see the following code
var app = angular.module('myApp', []);
app.controller("ctrlCarLists", function () {
var self = this;
self.data = 'hello';
self.showCars = function () {
alert("Ford, Toyata, Mercedes");
};
});
and change your html to this
<div ng-app="myApp">
<div ng-controller="ctrlCarLists as cars">
<button ng-click="cars.showCars()">
Cars
</button>
</div>
</div>
'this' will an object in side the controller. you can see the data by write {{cars.data}}
in your example
self.showCars is a function smiler to $scope.showCars ,$scope.showCars smiler to $scope.data a variable can access in the controller.
Trying firebase for the first time. Got the whole thing working in a plunkr here:
http://plnkr.co/3WIrBn
var app = angular.module('myApp',['firebase']);
app.factory('chatMessages',["$firebaseArray",function($firebaseArray){
var ref = new Firebase('https://scanapp.firebaseIO.com/tut');
return $firebaseArray(ref);
}]);
app.controller('MyController'['$scope','chatMessages',function($scope,chatMessages){
$scope.test = 'hello world';
$scope.user = "anonymouse";
$scope.messages = chatMessages;
$scope.addMessage = function(){
$scope.messages.$add({
from: $scope.user,
content: $scope.message
});
$scope.message = '';
};
}]);
I tried following their tutorials on their site, did their quick start stuff as well as read the docs thoroughly, but I keep getting the error above:
"Error: Key content was undefined. Cannot pass undefined in JSON. Use null instead."
I can get it all working in the above plunk, so I understand the concepts. Then I copied that same code from the plunk, and CDN links to my project, same error. Im using ionic framework for a web-based app. Angular and everything is still working fine,I just get the error when trying to hit the "add" button to run the function.
UPDATE: It definitely has something to do with inputs. If I set the "from" and "content" key and field as strings rather than bound to $scope, it works:
$scope.addMessage = function(){
$scope.messages.$add({
from: 'test',
content: 'stuff'
});
$scope.message = '';
};
But obviously that isn't useful other than sending the same data over and over again.
You have your $scope.messages in a form. The form creates a new scope. Remove the form and replace your button with the following:<button ng-click="addMessage()">Add</button>
This doesn't create a new scope and your message will be added successfully to your firebase.
At least it worked for me.
Add the models to the function
$scope.addMessage = function(user,message) {
$scope.messages.$add({
user,
body: message
});
//RESET MESSAGE
$scope.msg = "";
}
and on your form
<label class="item item-input">
<span class="input-label">Name</span>
<input type="text" name="username" ng-model="user" >
</label>
<label class="item item-input">
<span class="input-label">Message</span>
<input type="text" name="password" ng-model="message" >
</label>
<button class="button button-full button-positive" ng-click="addMessage(user,message)"> Send </button></pre>
Best of luck.
I'm pretty new to angular js but it seems like my simple code should work. Here is the html:
<body ng-app="MyHomepage">
<div ng-controller="RedditLoad">
{{a}}
<ul>
<li ng-repeat="article in a">
{{article.data.title}}
</li....
and here is my angualr_app.js:
var App = angular.module('MyHomepage', [])
function RedditLoad($scope){
$.getJSON("http://www.reddit.com/.json?jsonp=?", function(data) {
var data_array = [];
$.each(data.data.children, function(i,item){
data_array.push(item);
});
console.log(data_array);
$scope.a = data_array;
});
}
What am I doing wrong? console.log(data_array); is showing the correct values but the data wont seem to get passed to the template.
The getJSON callback isn't executed in the angular context so angular doesn't know about your changes and won't refresh the bindings. When code is called from an external source (like a jQuery event ), you have to encapsulate your scope changes in an $apply call:
$scope.$apply(function{
$scope.a = data_array;
}