AngularJS RouteParams - javascript

I dont understand why but when i console.log() both box and box.color its telling me its undefined...I tried many different methods to solve this problem but it all failed.
Cloud9
Plunker
And here is script.js:
var app = angular.module('LoginApp', ["firebase", "ngRoute", "ngCookies"])
app.provider("box", function ()
{
var hex = "SomeColor";
var UID = 3;
return {
setColor: function (value)
{
UID = value
},
$get: function ()
{
return {
color: hex
}
}
}
})
app.config(function ($routeProvider, $cookiesProvider) {
$routeProvider
.when('/', {
templateUrl: 'HtmlFiles/registration.html',
controller: 'regController'
})
.when('/logIn', {
templateUrl: 'HtmlFiles/login.html',
controller: 'loginController'
})
.when('/Chat', {
templateUrl: 'HtmlFiles/Chat.html',
controller: 'chatController'
})
.when('/Test' , {
template: '<h3>This is just a testing phase</h3>',
controller: 'Testing'
})
.when('/userSettings', {
templateUrl: 'HtmlFiles/userSettings.html',
controller: 'userSettingsController'
})
.when('/room', {
templateUrl: 'HtmlFiles/room.html',
controller: 'roomController'
})
.otherwise({
redirectTo: '/'
});
});
app.controller('Testing', ["$scope","roomService", "roomProvider", function($scope, roomService, roomProvider){
console.log("This is from the Controller Service: " + roomService.room.roomUID)
console.log("This is from the Controller Provider: " + roomProvider.$get)
}
])
app.factory("Auth", ["$firebaseAuth",
function($firebaseAuth) {
var ref = new Firebase("https://chattappp.firebaseio.com/");
return $firebaseAuth(ref);
}
]);
app.factory("Ref", function(){
var ref = new Firebase("https://chattappp.firebaseio.com/")
return ref;
})
app.factory("UniPosts" , function(){
var ref = new Firebase("https://postss.firebaseio.com/")
return ref;
});
app.service('getCookieService', ["$cookieStore", "$scope",
function($cookieStore, $scope){
this.getCookie = function(name){
$cookieStore.get(name)
}
}
])
roomController.js:
app.controller('roomController', ["$scope", "Auth", "Ref", "AuthService", "roomService","$http",
function($scope, Auth, Ref, AuthService, roomService, $http,box) {
// Sweet Alert :)
function generateRandomStringToken(length) {
var string = "";
var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < length; i++){
string += characters.charAt(Math.floor(Math.random() * characters.length));
}
return string;
}
swal({
title: "Room",
text: "What do you want your room name to be?",
type: "input",
showCancelButton: true,
closeOnConfirm: false,
animation: "slide-from-top",
inputPlaceholder: "Write something"
}, function(inputValue) {
if (inputValue === false) return false;
if (inputValue === "") {
swal.showInputError("You need to write something!");
return false
}
swal("Nice!", "You wrote: " + inputValue, "success");
$scope.$apply(function () {
$scope.roomNameModel = inputValue
});
console.log($scope.roomNameModel)
var redirectPage = generateRandomStringToken(10)
console.log("User gets redirected to : " + redirectPage + " ...")
roomService.setRoomUID(redirectPage);
console.log(roomService.room.roomUID)
console.log(box) //Undefined...
console.log("From Provider : " + box.color)//box.color is undefined..
});
}
])
//window.location.hash = "/Test"
EDIT 2: Ok Now it works but im confused on how to use it on app.config.. i My provider is Hash:
app.provider("Hash", function ()
{
var UID = 0;
return {
$get: function ()
{
return {
setHash: function (value)
{
UID = value;
},
getHash: function()
{
return UID;
}
}
}
}
})
And when it goes to the controller i set the hash and get the has ... roomControler.js:
app.controller('roomController', ["$scope", "Auth", "Ref", "AuthService", "roomService","$http", "Hash",
function($scope, Auth, Ref, AuthService, roomService, $http,Hash) {
// Sweet Alert :)
function generateRandomStringToken(length) {
var string = "";
var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < length; i++){
string += characters.charAt(Math.floor(Math.random() * characters.length));
}
return string;
}
swal({
title: "Room",
text: "What do you want your room name to be?",
type: "input",
showCancelButton: true,
closeOnConfirm: false,
animation: "slide-from-top",
inputPlaceholder: "Write something"
}, function(inputValue) {
if (inputValue === false) return false;
if (inputValue === "") {
swal.showInputError("You need to write something!");
return false
}
swal("Nice!", "You wrote: " + inputValue, "success");
$scope.$apply(function () {
$scope.roomNameModel = inputValue
});
console.log($scope.roomNameModel)
var redirectPage = generateRandomStringToken(10)
console.log("User gets redirected to : " + redirectPage + " ...")
roomService.setRoomUID(redirectPage);
console.log(roomService.room.roomUID);
Hash.setHash(redirectPage);
console.log("From Provider : " + Hash.getHash())
window.location.hash = "/Test"
});
}
])
Now what i want to do is in my app.config() i want to say when it is in Hash.getHash() Go to template: , and controller:
So something like this....
app.config(function ($routeProvider, $cookiesProvider, Hash) {
$routeProvider.
when('/' + Hash.getHash(), {
template: '<h4> Your in Room',
controller: 'Test
})
});
app.controller('Testing', ["$scope","roomService","Hash",function($scope, roomService, Hash){
console.log("This is from the Controller Service: " + roomService.room.roomUID)
console.log(Hash.getHash())//This Logs right. :D
}
])
EDIT 3
What i was trying to say earlier was that i want to somehow configure the randomly generated Hash in my app.config() when statements. so in my app.config. WHEN the USER is in /RANDOMLYGENERATEDHASH have a template: '<h1>Test</h1>' . This is what i tried but dosent workk...
It is the fourth one on the .when() Statements..
app.config(function ($routeProvider, $cookiesProvider, HashProvider){
$routeProvider
.when('/', {
templateUrl: 'HtmlFiles/registration.html',
controller: 'regController'
})
.when('/logIn', {
templateUrl: 'HtmlFiles/login.html',
controller: 'loginController'
})
.when('/Chat', {
templateUrl: 'HtmlFiles/Chat.html',
controller: 'chatController'
})
.when('/' + HashProvider , {
templete: '<h1>Test</h1>'
})
.when('/userSettings', {
templateUrl: 'HtmlFiles/userSettings.html',
controller: 'userSettingsController'
})
.when('/room', {
templateUrl: 'HtmlFiles/room.html',
controller: 'roomController'
})
.otherwise({
redirectTo: '/'
});
});
And here is the provider now..
app.provider("Hash", function ()
{
var UID = 0;
var _getHash = function()
{
return UID;
};
return {
getHash: _getHash,
$get: function ()
{
return {
setHash: function (value)
{
UID = value;
},
getHash: _getHash
}
}
}
})
EDIT 4
Ok This is my roomcontroller.js Now..:
(Important detail at bottom of controller)
app.controller('roomController', ["$scope", "Auth", "Ref", "AuthService", "roomService","$http", "Hash","$routeParams",
function($scope, Auth, Ref, AuthService, roomService, $http,Hash, $routeParams) {
// Sweet Alert :)
function generateRandomStringToken(length) {
var string = "";
var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < length; i++){
string += characters.charAt(Math.floor(Math.random() * characters.length));
}
return string;
}
swal({
title: "Room",
text: "What do you want your room name to be?",
type: "input",
showCancelButton: true,
closeOnConfirm: false,
animation: "slide-from-top",
inputPlaceholder: "Write something"
}, function(inputValue) {
if (inputValue === false) return false;
if (inputValue === "") {
swal.showInputError("You need to write something!");
return false
}
swal("Nice!", "You wrote: " + inputValue, "success");
$scope.$apply(function () {
$scope.roomNameModel = inputValue
});
console.log($scope.roomNameModel)
var redirectPage = generateRandomStringToken(10)
console.log("User gets redirected to : " + redirectPage + " ...")
roomService.setRoomUID(redirectPage);
console.log(roomService.room.roomUID);
Hash.setHash(redirectPage);
console.log("From Provider : " + Hash.getHash())
$routeParams.hash = Hash.getHash()
});
}
])
and script.js(Note this is not the only ones i have. You can see all other on above link on Cloud9(Plunk not updated)):
var app = angular.module('LoginApp', ["firebase", "ngRoute", "ngCookies", 'ngMessages'])
app.provider("Hash", function ()
{
var UID = 0;
var _getHash = function()
{
return UID;
};
return {
getHash: _getHash,
$get: function ()
{
return {
setHash: function (value)
{
UID = value;
},
getHash: _getHash
}
}
}
})
app.config(function ($routeProvider, $cookiesProvider, HashProvider){
$routeProvider
.when('/', {
templateUrl: 'HtmlFiles/registration.html',
controller: 'regController'
})
.when('/logIn', {
templateUrl: 'HtmlFiles/login.html',
controller: 'loginController'
})
.when('/Chat', {
templateUrl: 'HtmlFiles/Chat.html',
controller: 'chatController'
})
.when('/:Hash', {
template: '<h1>TEST TEST</h1>',
controller: 'any controller'
})
.when('/userSettings', {
templateUrl: 'HtmlFiles/userSettings.html',
controller: 'userSettingsController'
})
.when('/room', {
templateUrl: 'HtmlFiles/room.html',
controller: 'roomController'
})
.otherwise({
redirectTo: '/'
});
});
app.controller('Testing', ["$scope","roomService","Hash",function($scope, roomService, Hash){
console.log("This is from the Controller Service: " + roomService.room.roomUID)
console.log(Hash.getHash())
}
])
app.factory("Auth", ["$firebaseAuth",
function($firebaseAuth) {
var ref = new Firebase("https://chattappp.firebaseio.com/");
return $firebaseAuth(ref);
}
]);
app.factory("Ref", function(){
var ref = new Firebase("https://chattappp.firebaseio.com/")
return ref;
})
app.factory("UniPosts" , function(){
var ref = new Firebase("https://postss.firebaseio.com/")
return ref;
});
app.service('getCookieService', ["$cookieStore", "$scope",
function($cookieStore, $scope){
this.getCookie = function(name){
$cookieStore.get(name)
}
}
])
[1]: https://ide.c9.io/amanuel2/chattapp
[2]: https://plnkr.co/edit/ToWpQCw6GaKYkUegFjMi?p=preview

There are two problems in your code:
Definition of "roomController"
app.controller('roomController', ["$scope", "Auth", "Ref",
"AuthService", "roomService","$http",
function($scope, Auth, Ref, AuthService, roomService,
$http,box) {})
Just match the parameters and their declarations and you will see that you missed a declaration for the "box" parameter. The correct "roomController" definition should be like this:
app.controller('roomController', ["$scope", "Auth", "Ref", "AuthService", "roomService","$http", "box",
function($scope, Auth, Ref, AuthService, roomService, $http,box)
"box" provider. You defined "setColor" method as the configuration method of provider, but you are trying to use it as a provider result method. The corrected version should be like this:
app.provider("box", function ()
{
var hex = "SomeColor";
var UID = 3;
return {
$get: function ()
{
return {
color: hex,
setColor: function (value)
{
UID = value
}
}
}
}
})
Angular Providers
Answer to EDIT2:
You defined HashProvider. To configure it in app.config you should pass argument as HashProvider (not just Hash, BUT when you will try to use it anywhere except app.config you should inject it as Hash). So your app.config declaration should be like this:
app.config(function ($routeProvider, $cookiesProvider, HashProvider)
...and to let you access the getHash method it's necessary to move it to the provider configuration, for example like this:
app.provider("Hash", function ()
{
var UID = 0;
var _getHash = function()
{
return UID;
};
return {
getHash: _getHash,
$get: function ()
{
return {
setHash: function (value)
{
UID = value;
},
getHash: _getHash
}
}
}
})
Answer to EDIT3:
Now I got what you are trying to do. And the thing is that you are trying to do it wrong :). The right way is more simple. You have to configure route with param, for example like this:
.when('/:hash', {
template: '<h1>TEST TEST</h1>',
controller: 'any controller'
})
And place it just after your last route. After that, in controller you may access hash by using $routeParams object. For example like this:
$routeParams.hash
And after that in controller you may analyze if it's right hash and do necessary stuff, or redirect user somewhere if hash is invalid.

Related

webpack angularjs function returns string instead of object

I am creating webpage with webpack and Ive got strange error.
Data must be a valid JSON object. Received: ".... Undefined
index: id
So, I checked my objects which i sending. Then, when my service to get ID returns something like this in console log:
ƒ (){
return id;
}
So, I know that I've to run function first, then html template. Where I can get the error if we are talking about webpack?
It's my app.js, where I configure service and templates with controllers:
const css = require('./src/style/app.scss');
var angular = require('angular');
var ngRoute = require('angular-route');
var ngModule = angular.module('app', ['ngRoute']);
require('./src/js/contact')(ngModule);
require('./src/js/adminNetworks')(ngModule);
require('./src/js/automatic')(ngModule);
require('./src/js/login')(ngModule);
require('./src/js/program')(ngModule);
require('./src/js/register')(ngModule);
require('./src/js/main')(ngModule);
ngModule.service('user', function(){
var username;
var loggedin = false;
var id;
this.getName = function(){
return username;
};
this.setID = function(userID){
id = userID;
};
this.getID = function(){
return id;
};
this.isUserLoggedIn = function(){
if(!!localStorage.getItem('login')){
loggedin = true;
var data = JSON.parse(localStorage.getItem('login'));
username = data.username;
id = data.id;
}
return loggedin;
};
this.saveData = function(data){
username = data.user;
id = data.id;
loggedin = true;
localStorage.setItem('login', JSON.stringify({
username: username,
id: id
}));
};
this.clearData = function(){
localStorage.removeItem('login');
username="";
id="";
loggedin = false;
}
})
ngModule.controller('IndexController', ['$scope', 'user', function ($scope, user) {
$scope.aa = function(){
console.log(user.get);
}
}])
ngModule.config(function($routeProvider, $locationProvider){
$locationProvider.hashPrefix('');
$routeProvider
.when('/', {
templateUrl: 'main.html',
controller: 'MainCtrl'
})
.when('/program', {
templateUrl: 'program.html',
controller: 'ProgramCtrl',
resolve: {
check: function($location, user){
if(!user.isUserLoggedIn()){
$location.path('/');
alert('Musisz być zalogowany')
}
}
}
})
.when('/administration', {
templateUrl: 'adminNetworks.html',
controller: 'NetworkCtrl'
})
.when('/automatic', {
templateUrl: 'automatic.html',
controller: 'AutomaticCtrl'
})
.when('/contact', {
templateUrl: 'contact.html',
controller: 'ContactCtrl'
})
.when('/registry', {
templateUrl: 'register.html',
controller: 'RegisterCtrl'
})
.when('/login', {
templateUrl: 'login.html',
controller: 'LoginCtrl'
})
.when('/logout', {
resolve: {
deadResolve: function($location, user){
user.clearData();
$location.path('/');
}
}
})
.otherwise({
redirectTo: "/"
});
});
Firstly, I thought, that it's because of load chunks like this:
plugins: [
new HtmlWebpackPlugin({
title: 'Główna',
hash: true,
allChunks: true,
template: './src/html/index.html'
}),
new HtmlWebpackPlugin({
title: 'Main',
hash: true,
chunks: ['main'],
filename: 'main.html',
template: './src/html/main.html'
}),
but when I removed chunks section, it's still the same.
Please at least for any ideas.
#Edit - my new pass sender:
module.exports = function(ngModule) {
ngModule.controller('MainCtrl', ['$scope', '$http','user', function ($scope, $http, user) {
$scope.user = user.getName();
console.log("LOCAL STORAGE");
console.log(localStorage);
$scope.newPass = function(){
debugger;
var password = $scope.newpassword;
$http({
url: 'http://localhost/webpack/updatePass.php',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: 'newPass='+password+'&id='+user.getID()
}).then(function(response){
if(response.data.status =='done') {
alert('Changed');
}else {
alert('error');
}
})
}
}])
}

Error in linking page

I had a Problem in linking pages. Suppose, After Login from URL "/admin_1_angularjs/login.html",
the dashboard.html page should be Appear from this URL "/admin_1_angularjs/#/dashboard.html". instead it appeared in "/admin_1_angularjs/#/login.html" link. How do i fix this? here is my angularJS Controller...
MetronicApp.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
// Redirect any unmatched url
$urlRouterProvider.otherwise("/login.html");
app.version = '1454574448';
$stateProvider.state('login', {
url: "/login.html",
templateUrl: 'login.html?_=' + app.version,
controller: 'login'
})
.state('dashboard', {
url:"/dashboard.html",
templateUrl: 'views/profile/dashboard.html?_=' + app.version,
controller: 'dashboard'
})
this is my login controller.
var app = angular.module('myApp', []);
app.controller('login', ['$window','$scope','$timeout', function ($window,$scope,$timeout) {
$scope.hasError = false;
$scope.errorMessage = "";
$scope.input = {
username: '',
password: ''
};
$scope.counter = 0;
$scope.isLoading = false;
$scope.setError = function (hasError) {
$scope.hasError = hasError;
};
$scope.login = function () {
$scope.isLoading = true;
var postData = {
clazz: "com.smk.aps.server.model.rpc.request.RPCAdminLogin",
signature: "",
data: {
// requestLoginID: app.uuid.v4(),
// requestUsername: $scope.input.username,
// requestPassword: CryptoJS.SHA1($scope.input.password).toString()
}
};
postData.data._class = postData.clazz;
$timeout(function (data,status) {
$scope.isLoading = false;
if ($scope.hasError = true) {
if($scope.counter == 0) {
$scope.errorMessage = "Invalid username or password. Error code = " + $scope.counter;
console.log($scope.errorMessage);
$scope.counter++;
} else if ($scope.counter == 1) {
$scope.errorMessage = "Server busy please try again later. Error code = " + $scope.counter;
console.log($scope.errorMessage);
$scope.counter++;
} else {
$window.location.href = "/admin_1_angularjs/";
}
}
}, 2000);
You have to set HTML5 mode to true to get desired result. Please refer to HTML5Mode section of following link for more details.
https://docs.angularjs.org/guide/$location

Angular extract array from expected object response

I am working with wordpress' rest api and I am extracting a list of posts which allow the user to see a single post. Now I want to include the comments as well but I cannot wrap my head around this. I am using a factory for the calls:
.factory('Articles', function ($http) {
var articles = [];
storageKey = "articles";
function _getCache() {
var cache = localStorage.getItem(storageKey );
if (cache)
articles = angular.fromJson(cache);
}
return {
all: function () {
return $http.get("http://www.examplesite.com/tna_wp/wp-json/posts?filter[category_name]=test").then(function (response) {
articles = response.data;
console.log(response.data);
return articles;
});
},
get: function (articleId) {
if (!articles.length)
_getCache();
for (var i = 0; i < articles.length; i++) {
if (parseInt(articles[i].ID) === parseInt(articleId)) {
return articles[i];
}
}
return null;
}
}
})
My controller:
.controller('ExampleCtrl', function ($scope, $stateParams, _, Articles) {
$scope.articles = [];
Articles.all().then(function (response){
$scope.articles = response;
window.localStorage.setItem("articles", JSON.stringify(response));
},
function (err) {
if(window.localStorage.getItem("articles") !== undefined) {
$scope.articles = JSON.parse(window.localStorage.getItem("articles"));
}
}
);
$scope.doRefresh = function() {
Articles.all().then(function (articles){
var loadedIds = _.pluck($scope.articles, 'id');
var newItems = _.reject(articles, function (item){
return _.contains(loadedIds, item.id);
});
$scope.articles = newItems.concat($scope.articles);
$scope.$broadcast('scroll.refreshComplete');
});
};
})
//THIS IS WHERE I AM TRYING AND FAILING
.controller('ExampleInnerCtrl', function ($http, $scope, $stateParams, $cordovaSocialSharing, $ionicModal, Articles) {
$scope.article = Articles.get($stateParams.articleId);
var url = Articles.get($stateParams.articleId);
$scope.comments = [];
$http.get("http://www.example.com/tna_wp/wp-json/posts/" +url+ "/comments").then(function (response, commentId) {
$scope.comments = response.data;
console.log(response.data);
return $scope.comments;
});
$scope.comment = $stateParams.commentId;
$ionicModal.fromTemplateUrl('gauteng-comments.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal
})
$scope.openModal = function() {
$scope.modal.show()
}
$scope.closeModal = function() {
$scope.modal.hide();
};
$scope.$on('$destroy', function() {
$scope.modal.remove();
});
$scope.sharePost = function(link){
window.plugins.socialsharing.share('I just read this article on The New engage: ', null, null, "http://example.com" + link);
};
})
now in the controller if I include the post id manually I can get the comments for that post, however I cannot seem to store that post ID in a variable to use
--------EDIT
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: "/app",
abstract: true,
templateUrl: "templates/menu.html",
controller: "NavCtrl"
})
.state('app.home', {
url: "/home",
views: {
'menuContent': {
templateUrl: "templates/home.html"
}
}
})
.state('app.provinces', {
url: "/provinces",
views: {
'menuContent': {
templateUrl: "templates/provinces.html"
}
}
})
.state('app.example', {
url: "/provinces/example",
views: {
'menuContent': {
templateUrl: "templates/example.html",
controller: "ExampleCtrl"
}
}
})
.state('app.exampleSingle', {
url: "/provinces/example/:articleId",
views: {
'menuContent': {
templateUrl: "templates/exampleSingle.html",
controller: "ExampleInnerCtrl"
}
}
})
;
$urlRouterProvider.otherwise("/app/home");
});
Ok it was my stupidity... I just stored the variable as: var url = $scope.article.ID;

Message update in AngularJS

New to AngularJS and having an issue with updating message for either the for loop or angular.
Right now the two Angular functions (login and register) are only working for the last User, "Bilbo".
The login function does not return the appropriate message for if the User exists but the password is not correct, for all users except the last user, Bilbo.
For the register function it should be constantly checking to see if a name is taken or free, but it only says taken for the last user as well, Bilbo.
Not sure what I am doing wrong with combination of the for-loop and AngularJS as I would like to the message to work on all users.
PLUNKER DEMO
JS Code
var app = angular.module("app", ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'pages/home.html',
controller: 'HomeController'
})
.when('/home', {
templateUrl: 'pages/home.html',
controller: 'HomeController'
})
.when('/login', {
templateUrl: 'pages/login.html',
controller: 'LoginController'
})
.when('/account', {
templateUrl: 'pages/account.html',
controller: 'AccountController'
})
.when('/unknown', {
templateUrl: 'pages/unknown.html',
controller: 'UnknownController'
})
.otherwise({
redirectTo: '/unknown'
});
});
app.factory('userService', function() {
return {
users: [{
name: "John",
password: "12345"
}, {
name: "Austin",
password: "intern"
}, {
name: "Sally",
password: "noob"
}, {
name: "Bilbo",
password: "Baggins"
}]
};
});
app.controller('LoginController', function($scope, $location, userService) {
$scope.credentials = {
username: "",
password: ""
};
$scope.credentialsR = {
username: "",
password: ""
};
$scope.login = function() {
for (var i = 0; i < userService.users.length; i++) {
if (userService.users[i].name === $scope.credentials.username) {
if (userService.users[i].password === $scope.credentials.password) {
$location.path("/home");
} else {
$scope.messageLogin = "Incorrect login details";
}
} else {
$scope.messageLogin = "Username does not exist";
}
}
};
$scope.checkName = function() {
for (var i = 0; i < userService.users.length; i++) {
if (userService.users[i].name === $scope.credentialsR.username) {
$scope.messageRegister = "Taken";
} else {
$scope.messageRegister = "Available";
}
}
};
});
app.controller('HomeController', function($scope) {
});
app.controller('AccountController', function($scope, userService) {
$scope.userList = userService.users;
});
app.controller('UnknownController', function($scope) {
});
You have to immediately return if the user is found in the loop, instead of continue looping.
$scope.login = function() {
for (var i = 0; i < userService.users.length; i++) {
if (userService.users[i].name === $scope.credentials.username) {
if (userService.users[i].password === $scope.credentials.password) {
$location.path("/home");
} else {
$scope.messageLogin = "Incorrect login details";
}
return;
}
}
$scope.messageLogin = "Username does not exist";
};
$scope.checkName = function() {
for (var i = 0; i < userService.users.length; i++) {
if (userService.users[i].name === $scope.credentialsR.username) {
$scope.messageRegister = "Taken";
return;
}
}
$scope.messageRegister = "Available";
};
Example Plunker: http://plnkr.co/edit/eBGLsBdI89WFhEAxyDgL?p=preview
That is because you do not exit the for loop after having found the matching name. Therefore, if the matching name is not the last, the following name will trigger the wrong behavior anyway.
You can use a return to exit the loop, or more elegantly separate the search with a dedicated function:
app.factory('userService', function() {
var users = [{
name: "John",
password: "12345"
}, {
name: "Austin",
password: "intern"
}, {
name: "Sally",
password: "noob"
}, {
name: "Bilbo",
password: "Baggins"
}];
return {
users: users,
findUserByName: function (userName) {
return users.filter(function (user) {
return user.name === userName;
})[0];
}
};
});
And then :
$scope.login = function() {
var user = userService.findUserByName($scope.credentials.username);
if(user) {
if(user.password === $scope.credentials.password){
$location.path("/home");
} else {
$scope.messageLogin = "Incorrect login details";
}
} else {
$scope.messageLogin = "Username does not exist";
}
};
$scope.checkName = function() {
var user = userService.findUserByName($scope.credentials.username);
if(user) {
$scope.messageRegister = "Taken";
} else {
$scope.messageRegister = "Available";
}
};

AngularJS ui-router $state.go('^') only changing URL in address bar, but not loading controller

I am trying to create a "Todo App" with angularjs ui-router. It has 2 columns:
Column 1: list of Todos
Column 2: Todo details or Todo edit form
In the Edit and Create controller after saving the Todo I would like to reload the list to show the appropriate changes. The problem: after calling $state.go('^') when the Todo is created or updated, the URL in the browser changes back to /api/todo, but the ListCtrl is not executed, i.e. $scope.search is not called, hence the Todo list (with the changed items) is not retrieved, nor are the details of the first Todo displayed in Column 2 (instead, it goes blank).
I have even tried $state.go('^', $stateParams, { reload: true, inherit: false, notify: false });, no luck.
How can I do a state transition so the controller eventually gets executed?
Source:
var TodoApp = angular.module('TodoApp', ['ngResource', 'ui.router'])
.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/api/todo');
$stateProvider
.state('todo', {
url: '/api/todo',
controller: 'ListCtrl',
templateUrl: '/_todo_list.html'
})
.state('todo.details', {
url: '/{id:[0-9]*}',
views: {
'detailsColumn': {
controller: 'DetailsCtrl',
templateUrl: '/_todo_details.html'
}
}
})
.state('todo.edit', {
url: '/edit/:id',
views: {
'detailsColumn': {
controller: 'EditCtrl',
templateUrl: '/_todo_edit.html'
}
}
})
.state('todo.new', {
url: '/new',
views: {
'detailsColumn': {
controller: 'CreateCtrl',
templateUrl: '/_todo_edit.html'
}
}
})
;
})
;
TodoApp.factory('Todos', function ($resource) {
return $resource('/api/todo/:id', { id: '#id' }, { update: { method: 'PUT' } });
});
var ListCtrl = function ($scope, $state, Todos) {
$scope.todos = [];
$scope.search = function () {
Todos.query(function (data) {
$scope.todos = $scope.todos.concat(data);
$state.go('todo.details', { id: $scope.todos[0].Id });
});
};
$scope.search();
};
var DetailsCtrl = function ($scope, $stateParams, Todos) {
$scope.todo = Todos.get({ id: $stateParams.id });
};
var EditCtrl = function ($scope, $stateParams, $state, Todos) {
$scope.action = 'Edit';
var id = $stateParams.id;
$scope.todo = Todos.get({ id: id });
$scope.save = function () {
Todos.update({ id: id }, $scope.todo, function () {
$state.go('^', $stateParams, { reload: true, inherit: false, notify: false });
});
};
};
var CreateCtrl = function ($scope, $stateParams, $state, Todos) {
$scope.action = 'Create';
$scope.save = function () {
Todos.save($scope.todo, function () {
$state.go('^');
});
};
};
I would give an example (a draft) of HOW TO nest edit into detail. Well, firstly let's amend the templates.
The Detail template, contains full definition of the detail. Plus it now contains the attribute ui-view="editView". This will assure, that the edit, will "replace" the detail from the visibility perspective - while the edit scope will inherit all the detail settings. That's the power of ui-router
<section ui-view="editView">
<!-- ... here the full description of the detail ... -->
</section>
So, secondly let's move the edit state, into the detail
// keep detail definition as it is
.state('todo.details', {
url: '/{id:[0-9]*}',
views: {
'detailsColumn': {
controller: 'DetailsCtrl',
templateUrl: '/_todo_details.html'
}
}
})
// brand new definition of the Edit
.state('todo.details.edit', { // i.e.: url for detail like /todo/details/1/edit
url: '/edit',
views: {
'editView': { // inject into the parent/detail view
controller: 'EditCtrl',
templateUrl: '/_todo_edit.html'
}
}
})
Having this adjusted state and template mapping, we do have a lot. Now we can profit from the ui-router in a full power.
We'll define some methods on a DetailCtrl (remember, to be available on the inherit Edit state)
var DetailsCtrl = function ($scope, $stateParams, Todos) {
$scope.id = $stateParams.id // keep it here
// model will keep the item (todos) and a copy for rollback
$scope.model = {
todos : {},
original : {},
}
// declare the Load() method
$scope.load = function() {
Todos
.get({ id: $stateParams.id })
.then(function(response){
// item loaded, and its backup copy created
$scope.model.todos = response.data;
$scope.model.original = angular.copy($scope.model.todos);
});
};
// also explicitly load, but just once,
// not auto-triggered when returning back from Edit-child
$scope.load()
};
OK, it should be clear now, that we do have a model with the item model.todos and its backup model.original.
The Edit controller could have two actions: Save() and Cancel()
var EditCtrl = function ($scope, $stateParams, $state, Todos) {
$scope.action = 'Edit';
// ATTENTION, no declaration of these,
// we inherited them from parent view !
//$scope.id .. // we DO have them
//$scope.model ...
// the save, then force reload, and return to detail
$scope.save = function () {
Todos
.update({ id: id })
.then(function(response){
// Success
$scope.load();
$state.go('^');
},
function(reason){
// Error
// TODO
});
};
// a nice and quick how to rollback
$scope.cancel = function () {
$scope.model.todos = Angular.copy($scope.model.original);
$state.go('^');
};
};
That should give some idea, how to navigate between parent/child states and forcing reload.
NOTE in fact, instead of Angular.copy() I am using lo-dash _.cloneDeep() but both should work
Huge thanks for Radim Köhler for pointing out that $scope is inherited. With 2 small changes I managed to solve this. See below code, I commented where I added the extra lines. Now it works like a charm.
var TodoApp = angular.module('TodoApp', ['ngResource', 'ui.router'])
.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/api/todo');
$stateProvider
.state('todo', {
url: '/api/todo',
controller: 'ListCtrl',
templateUrl: '/_todo_list.html'
})
.state('todo.details', {
url: '/{id:[0-9]*}',
views: {
'detailsColumn': {
controller: 'DetailsCtrl',
templateUrl: '/_todo_details.html'
}
}
})
.state('todo.edit', {
url: '/edit/:id',
views: {
'detailsColumn': {
controller: 'EditCtrl',
templateUrl: '/_todo_edit.html'
}
}
})
.state('todo.new', {
url: '/new',
views: {
'detailsColumn': {
controller: 'CreateCtrl',
templateUrl: '/_todo_edit.html'
}
}
})
;
})
;
TodoApp.factory('Todos', function ($resource) {
return $resource('/api/todo/:id', { id: '#id' }, { update: { method: 'PUT' } });
});
var ListCtrl = function ($scope, $state, Todos) {
$scope.todos = [];
$scope.search = function () {
Todos.query(function (data) {
$scope.todos = $scope.todos(data); // No concat, just overwrite
if (0 < $scope.todos.length) { // Added this as well to avoid overindexing if no Todo is present
$state.go('todo.details', { id: $scope.todos[0].Id });
}
});
};
$scope.search();
};
var DetailsCtrl = function ($scope, $stateParams, Todos) {
$scope.todo = Todos.get({ id: $stateParams.id });
};
var EditCtrl = function ($scope, $stateParams, $state, Todos) {
$scope.action = 'Edit';
var id = $stateParams.id;
$scope.todo = Todos.get({ id: id });
$scope.save = function () {
Todos.update({ id: id }, $scope.todo, function () {
$scope.search(); // Added this line
//$state.go('^'); // As $scope.search() changes the state, this is not even needed.
});
};
};
var CreateCtrl = function ($scope, $stateParams, $state, Todos) {
$scope.action = 'Create';
$scope.save = function () {
Todos.save($scope.todo, function () {
$scope.search(); // Added this line
//$state.go('^'); // As $scope.search() changes the state, this is not even needed.
});
};
};
I might have faced a similar problem the approach i took was to use $location.path(data.path).search(data.search); to redirect the page then in the controller I caught the $locationChangeSuccess event. I other words I use the $location.path(...).search(...) as apposed to $state.go(...) then caught the $locationChangeSuccess event which will be fired when the location changes occurs before the route is matched and the controller invoked.
var TodoApp = angular.module('TodoApp', ['ngResource', 'ui.router'])
.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/api/todo');
$stateProvider
.state('todo', {
url: '/api/todo',
controller: 'ListCtrl',
templateUrl: '/_todo_list.html'
})
.state('todo.details', {
url: '/{id:[0-9]*}',
views: {
'detailsColumn': {
controller: 'DetailsCtrl',
templateUrl: '/_todo_details.html'
}
}
})
.state('todo.edit', {
url: '/edit/:id',
views: {
'detailsColumn': {
controller: 'EditCtrl',
templateUrl: '/_todo_edit.html'
}
}
})
.state('todo.new', {
url: '/new',
views: {
'detailsColumn': {
controller: 'CreateCtrl',
templateUrl: '/_todo_edit.html'
}
}
})
;
})
;
TodoApp.factory('Todos', function ($resource) {
return $resource('/api/todo/:id', { id: '#id' }, { update: { method: 'PUT' } });
});
var ListCtrl = function ($scope, $state, Todos, todo.details) {
/*here is where i would make the change*/
$scope.$on('$locationChangeSuccess', function () {
$scope.search();
$route.reload();
});
$scope.todos = [];
$scope.search = function () {
Todos.query(function (data) {
$scope.todos = $scope.todos.concat(data);
});
};
$scope.search();
};
var DetailsCtrl = function ($scope, $stateParams, Todos) {
$scope.todo = Todos.get({ id: $stateParams.id });
};
var EditCtrl = function ($scope, $stateParams, $state, Todos, $location) {
$scope.action = 'Edit';
var id = $stateParams.id;
$scope.todo = Todos.get({ id: id });
$scope.save = function () {
Todos.update({ id: id }, $scope.todo, function () {
//here is where I would make a change
$location.path('todo.details').search($stateParams);
});
};
};
var CreateCtrl = function ($scope, $stateParams, $state, Todos, $location) {
$scope.action = 'Create';
$scope.save = function () {
Todos.save($scope.todo, function () {
//here is where I would make a change
$location.path('todo.details');
});
};
};
the $locationChangeSuccess event occurs before the route is matched and the controller invoked

Categories

Resources