Binding not working with Angular.js and Firebase Simple Login - angularjs

I'm seeing some odd behavior with the Firebase Simple Login when used with Angular.
I'm not able to get $scope variables to bind as expected. I would think that or $scope.test would change after successful login, but it doesn't. It stays false even after login. Given that this is my first Angular project, I'm guessing it's something simple, but I've looked all over and haven't found an answer.
The code is quite simple. First the HTML:
<body ng-app>
<div ng-controller="LoginController">
<div ng-hide="test">
<h1>Welcome. Please log in.</h1>
<p>Test is {{test}}</p>
<label>Username</label>
<input type="text" ng-model="username" />
<label>Password</label>
<input type="password" ng-model="password" />
<button ng-click="login()">Log in</button>
</div>
<button ng-show="test" ng-click="logout()">Log out</button>
</div>
<script type='text/javascript' src='https://cdn.firebase.com/js/client/1.0.6/firebase.js'></script>
<script type='text/javascript' src='https://cdn.firebase.com/js/simple-login/1.2.5/firebase-simple-login.js'></script>
<script type="text/javascript" src="js/lib/angular.js"></script>
<script type="text/javascript" src="js/controllers/LoginController.js"></script>
</body>
And the one controller:
function LoginController($scope) {
var FB = new Firebase("https://[myfirebase].firebaseio.com");
$scope.user = false;
$scope.error = false;
$scope.test = false;
$scope.auth = new FirebaseSimpleLogin(FB, function(error, user){
if(error) {
$scope.error = error;
} else if(user) {
// would expected binding to take effect here, but not
$scope.user = user;
$scope.test = true;
} else {
console.log("no user");
}
});
$scope.logout = function() {
this.auth.logout();
};
$scope.login = function () {
console.log("Attempting login");
this.auth.login('password', {
email: this.username,
password: this.password
});
};
}
Thanks to anyone who can point me in the right direction.

You need to use $scope.$apply() to let angular know you've changed something on the scope. You need to do this when integrating 3rd party libraries with watched scope variables.
$scope.auth = new FirebaseSimpleLogin(FB, function(error, user){
$scope.$apply(function() {
if(error) {
$scope.error = error;
} else if(user) {
// would expected binding to take effect here, but not
$scope.user = user;
$scope.test = true;
} else {
console.log("no user");
}
}
});

Related

Why isn't the form sending the text value from my form?

I'm following a tutorial to create a simple todo app using the MEAN stack. Everything was working fine until I moved the controllers and services into separate files. Now I can create a new todo but it doesn't get the text value. I can see in my mongoDB database that a new entry has been created but it doesn't have a text value. I've been looking all over my code but I can't find anything nor do I get any error or warnings in the developer tools of the browser.
Here is the code for the form:
<div id="todo-form" class="row">
<div class="col-sm-8 col-sm-offset-2 text-center">
<form>
<div class="form-group">
<!-- Bind this value to formData.text in Angular -->
<input type="text" class="form-control input-lg text-center" placeholder="Add a todo" ng-model="formData.text">
</div>
<button type="submit" class="btn btn-primary btn-lg" ng-click="createTodo()">Add</button>
</form>
</div>
</div>
Here is my service:
//todos.js service
//the service is meant to interact with our api
angular.module('todoService', [])
//simple service
//each function returns a promise object
.factory('Todos', function($http){
return {
get : function() {
return $http.get('/api/todos');
},
create : function(todoData){
return $http.post('/api/todos', todoData);
},
delete : function(id){
return $http.delete('/api/todos/' + id);
}
}
});
Here is my main controller which uses the service:
//main.js
var myApp = angular.module('todoController', []);
myApp.controller('mainController', ['$scope', '$http', 'Todos', function($scope, $http, Todos){
$scope.formData = {};
//GET
//get all the todos by using the service we created
Todos.get()
.success(function(data){
$scope.todos = data;
});
//CREATE
$scope.createTodo = function(){
Todos.create($scope.formData)
.success(function(data){
$scope.formData = {};
$scope.todos = data;
});
}
//DELETE
$scope.deleteTodo = function(id){
Todos.delete(id)
.success(function(data){
$scope.todos = data;
});
};
}]);
Lastly, here is the route for creating a todo:
var Todo = require('./models/todos');
//expose our routes to our app with module exports
module.exports = function(app){
//api
//get all todos
app.get('/api/todos', function(req, res){
Todo.find(function(err, todos){
if(err)
res.send(err);
res.json(todos);
});
});
//create to do
app.post('/api/todos', function(req, res){
Todo.create({
text: req.body.text,
done: false
}, function(err, todo){
if(err)
res.send(err);
//get and return all todos after creating the new one
Todo.find(function(err, todos){
if(err)
res.send(err);
res.json(todos);
});
});
});
To recap, for some reason the formData.text value doesn't get stored somewhere and I don't know why.
I can't say for sure with angular but normal HTML forms inputs need a name attribute to submit

Sharing data between controllers - Angularjs

i have a problem while im trying to share a data between two controllers.
Here is my code :
<html>
<head>
<title>My Angular App</title>
</head>
<body ng-app="MyTest">
<div ng-controller="ViewController as vmView">
<ul>
<li ng-repeat="singleItem in vmView.allData">
{{ singleItem }}
</li>
</ul>
{{ vmView.checkItOut }}
<input type="button" ng-click="vmView.justClick()" />
</div>
<div ng-controller="AddController as vmAdd">
<form ng-submit="vmAdd.saveChanges()">
<input type="text" ng-model="vmAdd.inputText" />
<input type="submit" />
</form>
</div>
<script src="angular.js"></script>
<script src="app.js"></script>
<script type="application/javascript">
angular.module('MyTest')
.factory('shareDataFactory', function($http, $q) {
var data = {};
data.list = $q.defer();
data.getAllData = function() {
$http.get('http://www.w3schools.com/angular/customers.php')
.then(function(response) {
data.list = $q.resolve(response.data.records);
});
return data.list.promise;
};
data.addData = function(newData) {
data.list.push(newData);
};
return data;
});
angular.module('MyTest')
.controller('ViewController', function ViewController(shareDataFactory) {
var vm = this;
vm.allData = shareDataFactory.getAllData();
vm.checkItOut = "Just checking ..";
vm.justClick = function() {
console.log(vm.allData);
}
});
angular.module('MyTest')
.controller('AddController', function AddController(shareDataFactory) {
var vm = this;
vm.inputText = "Hello";
vm.saveChanges = function() {
shareDataFactory.addData(vm.inputText);
// Clear the data
vm.inputText = "";
};
});
</script>
</body>
</html>
vm.allData its just not updating affter the request come back from the server.
i tried to solve this for a long time but without success.
thanks you everyone and have a lovely week,
rotem
Your code doesn't make much sense:
data.list = $q.defer();
So, data.list is a deferred object. But later
data.list = $q.resolve(response.data.records);
Ah, it's not a deferred anymore: it's being replaced by a resolved promise, unrelated to the promise returned by getAllData(). But later
data.list.push(newData);
Ah, that code thinks it's an array, and not a promise not a deferred.
That can't be right. If you want to be able to push, it must be an array. If you want to populate the array when the http promise is resolved, then push to this aray
It's also unclear what the service should do: it gets data from an HTTP service, but doesn't send the new values to that HTTP service. So, every time you'll call getAllData(), you'll lose the added values.
Anyway:
var list = [];
var getAllData = function() {
$http.get('http://www.w3schools.com/angular/customers.php')
.then(function(response) {
// clear the array
list.splice(0, list.length);
// copy every record to the array
response.data.records.forEach(function(record) {
list.push(record);
});
});
return list;
};
var addData = function(newData) {
list.push(newData);
};
return {
getAllData: getAllData,
addData: addData
};
Here you can find a working version of your code.
When data is loaded, you are replacing the bound list with a new one, so changes aren't getting reflected anymore.
Html
<div ng-controller="ViewController as vmView">
<ul>
<li ng-repeat="singleItem in vmView.allData">
{{ singleItem }}
</li>
</ul>
{{ vmView.checkItOut }}
<input type="button" ng-click="vmView.justClick()" />
</div>
<div ng-controller="AddController as vmAdd">
<form ng-submit="vmAdd.saveChanges()">
<input type="text" ng-model="vmAdd.inputText" />
<input type="submit" />
</form>
</div>
</body>
Javascript
var module = angular.module('MyTest', []);
module.service('shareDataFactory', function($http, $q) {
var data = {
list: []
};
$http.get('http://www.w3schools.com/angular/customers.php')
.then(function(response) {
Array.prototype.push.apply(data.list, response.data.records);
});
return {
getData: function() {
return data;
},
addData: function(newData) {
data.list.push(newData);
}
};
});
module.controller('ViewController', function ViewController($scope, shareDataFactory) {
$scope.allData = shareDataFactory.getData().list;
$scope.checkItOut = "Just checking ..";
$scope.justClick = function() {
console.log($scope.allData);
}
});
module.controller('AddController', function AddController($scope, shareDataFactory) {
$scope.inputText = "Hello";
$scope.saveChanges = function() {
shareDataFactory.addData($scope.inputText);
// Clear the data
$scope.inputText = "";
};
});

Login in angularjs

I have an idea of how to use post method for login, however, our new requirement is my API team has provided get method. How is this used in angular? Please help me. I am stuck on this problem as I am new to angular. Below is the API for get method:
http://183.82.48/HospitalManagementSystem/Service1.svc/LoginVerification/{EMAILID}/{PASSWORD}
You can try to construct the URI yourself.
<form ng-app="login" ng-controller="loginCtrl">
<span>Email</span><input ng-model="emailId" type="text" required><br>
<span>Password</span><input ng-model="password" type="password" required><br>
<button ng-click="login()">Login</button>
</form>
<script>
var app = angular.module('login', []);
app.controller('loginCtrl', function($scope, $http) {
$scope.login = function() {
$http.get('http://183.82.0.48/HospitalManagementSystem/Service1.svc/LoginVerification/' + $scope.emailId + '/' + $scope.password).then(
function (response) {
console.log(response.data);
// ...
},
function (error) {
console.log(error);
// ...
}
)
}
});
</script>

Angularjs checkbox initialization issue using json object

So i have a checkbox page barely working, the issue is when i first start this page, the checkbox is not checked, even though i try to initialize it from backend node server. No error in browser debugger though.
in the server mye,
app.get('/2getMyDiagValue', function(req, res)
{
console.log("get my diag");
var formDataArray = { "formDataObjects": [
{"flagName":"myStuff1", "flagVal":0},
{"flagName":"myStuff2", "flagVal":1}
]};
res.contentType('application/json');
res.send(formDataArray);
});
app.post('/2setMyDiagValue', function(req, res)
{
......
}
in the client mye,
app.controller('myDiagController', function($scope, $http, $routeParams, QueryMyService) {
$scope.message = 'SID Diagnostics';
// using http.get() to get existing my setting from server mye
QueryMyService.getInfoFromUrl7('/2getMyDiagValue').then(function(result) {
$scope.formData = result.formDataObjects;
}, function(error) {
alert("Error");
} );
$scope.submitForm = function() {
console.log("posting form data ...");
$http.post("/2setMyDiagValue",
JSON.stringify($scope.formData)).success(function(){} );
};
});
app.factory('QueryMyService', function($http, $q, $location) {
var factory = {};
var browserProtocol = 'http';
var port = ':1234';
var address = 'localhost';
var server = browserProtocol + '://' + address;
//////////////////////////////////////////////////////////
factory.getInfoFromUrl7 = function(myUrl) {
var deferred = $q.defer();
$http.get(myUrl).success(function(data) {
deferred.resolve(data);
}).error(function(){
deferred.reject();
});
return deferred.promise;
}
return factory;
}
checkbox webpage itself
<form ng-submit="submitForm()" ng-controller="myDiagController">
<div class="control-group" style="color:black">
<label>My Checkbox</label>
<div class="checkbox">
<label class="checbox-inline" >
<input class="big-checkbox" type="checkbox" ng-model="formData.myStuff1"
ng-true-value="1" ng-false-value="0" ng-checked="formData.myStuff1 == 1">
<h4>Message 1</h4>
<input class="big-checkbox" type="checkbox" ng-model="formData.myStuff2"
ng-true-value="1" ng-false-value="0" ng-checked="formData.myStuff2 == 1">
<h4>Message 2</h4>
</label>
</div>
<br>
<input class="btn-primary" type="submit">
</form>
i did try to modify ng-checked like this and the checkbox did show checked.
ng-checked="true"
well, just used "res.json" in the node.js side and made it work, guess i just don't have time to learn, while this fxxking company gave me a tough schedule

"Error: $apply already in progress" when using FireBaseAuthClient with AngularJS

I'm trying to record the logged in user in an AngularJS scope, but getting an error when the page first loads up.
Clicking "Login" seems to work, but then logout bails with the same "$apply already in progress" error.
I'm expecting I've just misunderstood how $apply works, can anybody help?
Update:
It works seamlessly if I wrap just the if (user) part in $apply() as follows.
var auth = new FirebaseAuthClient(ref, function(error, user) {
if (user) {
$scope.$apply(function(){ $scope.user = user; });
console.log(user);
} else if (error) {
// I can't vouch for this, haven't tested it
$scope.$apply(function(){ $scope.user = null; });
console.log(error);
} else {
$scope.user = null;
console.log("logged out");
}
});
Original code:
app.js:
var app = angular.module('app', ['firebase']);
controller.js:
app.controller('Login', ['$scope', 'angularFire',
function($scope, angularFire) {
$scope.loginstatus = 'logged out';
var ref = new Firebase("https://app.firebaseio.com/");
var auth = new FirebaseAuthClient(ref, function(error, user) {
if (user) {
$scope.$apply(function(){ $scope.loginstatus = 'logged in'; });
} else if (error) {
$scope.$apply(function(){ $scope.loginstatus = 'error'; });
alert("Login error: " + error);
} else {
$scope.$apply(function(){ $scope.loginstatus = 'logged out'; });
}
});
$scope.login = function(provider, args) {
auth.login(provider, args);
}
$scope.logout = function() {
auth.logout();
}
}]);
index.html:
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<title>App</title>
<script type="text/javascript" src="https://cdn.firebase.com/v0/firebase.js">
<script type="text/javascript" src='https://cdn.firebase.com/v0/firebase-auth-client.js'></script></script>
<script type="text/javascript" src="lib/angular/angular.js"></script>
<script type="text/javascript" src="lib/angularFire.js"></script>
<script type="text/javascript" src="js/app.js"></script>
<script type="text/javascript" src="js/controllers.js"></script>
</head>
<body ng-controller="Login">
<p>Login status: {{loginstatus}}</p>
<div class="container">
<h1>Login</h1>
<p>
<button ng-hide="user" ng-click="login('twitter')" class="btn btn-primary btn-large">Login</button>
<button ng-show="user" ng-click="logout()" class="btn btn-primary btn-large">Logout</button>
</p>
</div>
</body>
</html>
$apply is only needed when you're outside of the context of Angular (like a setTimeout, setInterval, or non-Angular XHR callback).
Since FireBaseAuthClient is a tool written with Angular in mind and injected into your controller, it's likely that the callbacks are already wrapped in $scope.$apply. You can fix your code by removing $scope.$apply, so just:
var ref = new Firebase("https://app.firebaseio.com/");
var auth = new FirebaseAuthClient(ref, function(error, user) {
if (user) {
$scope.loginstatus = 'logged in';
} else if (error) {
$scope.loginstatus = 'error';
alert("Login error: " + error);
} else {
$scope.loginstatus = 'logged out';
}
});

Resources