templateUrl changes when refresh or reload page in AngularJS - html

I am using angular packet template. Here 11 pages loaded and 11 different buttons like the following:
Here is the route code:
state('app.pagelayouts.fixedsidebar1', {
url: "/fixed-sidebar",
templateUrl: "assets/views/page-1.html",
resolve: loadSequence('d3', 'ui.knob', 'countTo', 'dashboardCtrl'),
title: 'Fixed Sidebar',
ncyBreadcrumb: {
label: 'Fixed Sidebar'
},
controller: function ($scope) {
$scope.setLayout();
$scope.app.layout.isSidebarFixed = true;
$scope.$on('$routeChangeSuccess',function(){
$scope.templateUrl = $route.current.templateUrl;
})
}
})
.state('app.pagelayouts.fixedsidebar2', {
url: "/fixed-sidebar",
templateUrl: "assets/views/page-2.html",
resolve: loadSequence('d3', 'ui.knob', 'countTo', 'dashboardCtrl'),
title: 'Fixed Sidebar',
ncyBreadcrumb: {
label: 'Fixed Sidebar'
},
controller: function($scope) {
$scope.setLayout();
$scope.app.layout.isSidebarFixed = true;
}
}).
page-3.html, page-4.html and so on....
Suppose I am in page-1.html, when I refresh it doesn't stay in page-1. Goes to another page. But it should be stay at page-1.html. The templateUrl is changing.
How can i fix it ?

One obvious problem is that you have same url for all the routes.
You should update it with a parameter indicating the template to load, so that when page is refreshed, UI Router knows which state to activate based on the url. For example:
state('app.pagelayouts.fixedsidebar1', {
url: "/fixed-sidebar/1",
templateUrl: "assets/views/page-1.html",
resolve: loadSequence('d3', 'ui.knob', 'countTo', 'dashboardCtrl'),
title: 'Fixed Sidebar',
ncyBreadcrumb: {
label: 'Fixed Sidebar'
},
controller: function($scope) {
$scope.setLayout();
$scope.app.layout.isSidebarFixed = true;
}
});
If all your routes are similar, you can create a single route with a param like:
state('app.pagelayouts.fixedsidebar', {
url: "/fixed-sidebar/:id",
templateUrl: function($stateParams) {
return "assets/views/page-" + $stateParams.id + ".html";
},
resolve: loadSequence('d3', 'ui.knob', 'countTo', 'dashboardCtrl'),
title: 'Fixed Sidebar',
ncyBreadcrumb: {
label: 'Fixed Sidebar'
},
controller: function($scope) {
$scope.setLayout();
$scope.app.layout.isSidebarFixed = true;
}
});

Related

AngularJS: How to create routes with ui-router for my application

I have a problem with my a tag - I have a page that present data according to the GET vars.
For example - /foo.php?opt=1 will show table of cities that each one will go to - /foo.php?city=4 that have table of schools that go to /foo.php?school=4 that show table of students etc..
The problem is that the first time it works - when I choose city it will show me the list of schools and change the url, but when I choose school, it changes the URL but I still see the city table, and only if I press F5 it will show me table students.
This is the code:
odinvite.php:
<?php
if (isset($_GET['city']))
{
include "odbycity.php";
}
else if (isset($_GET['school']))
{
include "odbyschool.php";
}
else
{
include "odshowcities.php";
}
?>
odshowcities.php:
<div ng-controller="allcities">
<button class="btn btn-info" ng-repeat="x in names">
<a href="/odinvite.php?city={{x.areaid}}">
{{x.areaname}}</a>
</button>
</div>
odbyschool.php:
<div ng-controller="odbycity">
<button class="btn btn-info" ng-repeat="x in names">
<a href="/odinvite.php?school={{x.schoolid}}">
{{x.school_name}}</a>
</button>
</div>
MyAngular.js:
var myApp = angular.module('myApp',[]);
myApp.config(function( $locationProvider) {
$locationProvider.html5Mode(true);
});
myApp.controller ('allcities', function ($scope, $http)
{
$http.get("fetch_json_sql.php?option=1")
.then(function (response)
{
$scope.names = response.data.result;
});
console.log($scope.names);
});
myApp.controller ('odbycity', function ($scope, $http, $location)
{
$scope.cityid=$location.search().city;
console.log($scope.cityid);
$http.get("fetch_json_sql.php?option=2&cityid="+$scope.cityid)
.then(function (response)
{
$scope.names = response.data.result;
});
});
myApp.controller ('odbyschool', function ($scope, $http ,$location)
{
$scope.schoolid = $location.search().school;
console.log($scope.schoolid);
$http.get("fetch_json_sql.php?option=4&schoolid="+$scope.schoolid)
.then(function (response)
{
$scope.names = response.data.result;
});
});
What can be the problem?
I tried to make 100% change of the URL - link and it didn't work. just changed the URL without redirect.
Thanks!
You should stop rendering your templates with a backend. AngularJS is for SPA. If you need data provided by a backend try to implement an API e.g. a RESTful API. you need to configure your routes for example like in this runnable demo plnkr. It uses ui-router. Please note, this is just a demo. You should be able to put your logic into that prototype. I prepared all routes you need by using some dummy data. Just include your existing API in the controllers and you should be fine.
var myApp = angular.module("myApp", ['ui.router']);
myApp.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.when("", "/main");
$stateProvider
.state("main", {
url: "/main",
templateUrl: "main.html"
})
.state("main.listSchools", {
url: "/listSchools/:schoolId",
templateUrl: "schools.html"
})
.state("main.listAreas", {
url: "/listAreas/:areaId",
templateUrl: "areas.html"
});
});
myApp.controller('mainMenuController', function ($scope) {
$scope.schools = [{
schoolid: 1,
name: 'Test School 1'
},{
schoolid: 5,
name: 'Test School 5'
},{
schoolid: 11,
name: 'Test School 11'
}];
$scope.areas = [{
areaid: 3,
name: 'Test area 3'
},{
areaid: 7,
name: 'Test area 7'
},{
areaid: 19,
name: 'Test area 7'
}];
});
myApp.controller('listSchoolController', function ($scope, $state) {
$scope.schoolId = $state.params.schoolId;
});
myApp.controller('listAreaController', function ($scope, $state) {
$scope.areaId = $state.params.areaId;
});

Stacking a modal over another modal using angularJS on clicking the backdrop

I am trying to make a modal appear on top of another modal (like a stack of modals) automatically when the user clicks on the backdrop of a modal or presses the escape button (in this case a dialog box to ask whether you want to progress further).
The problem is that I am not able to figure out how I can call the event's preventDefault() function as I feel that it is the solution to my problem. Currently, what happens is that on clicking the backdrop, the current modal vanishes and the second modal takes it's place instead of appearing above the current modal, putting it in the backdrop.
Here is my code snippet :
The beginning -
(function () {
'use strict';
angular
.module('controller.main', [])
.controller('Main', ['$location', '$state', '$uibModal', 'user', 'auth', 'model', function ($location, $state, $uibModal, user, auth, model) {
var vm = this;
The code in question that is supposed to do the expected task -
vm.openConfirmCancelDB = function (size)
{
$uibModal.open({
animation: vm.animationsEnabled,
templateUrl: '/views/confirmCancelProcessModal.html',
controller: 'Cancel',
controllerAs: 'cancel',
size: size,
backdrop: 'static',
resolve: {}
});
};
vm.openLogin = function (size)
{
var OLP = $uibModal.open(
{
animation: vm.animationsEnabled,
templateUrl: '/views/login.html',
controller: 'Modal',
controllerAs: 'modal',
size: size,
//backdrop: 'static',
resolve: {
inUser: function () {
var user = {};
return user;
}
}
});
OLP.result.then(function()
{
//event.preventDefault();
},
function ()
{
vm.openConfirmCancelDB('sm');
});
};
vm.register = function (size)
{
console.log(vm.registerform);
var RP = $uibModal.open(
{
animation: vm.animationsEnabled,
templateUrl: '/views/register.html',
controller: 'Registration',
controllerAs: 'modal',
//backdrop: 'static',
size: size,
resolve: {
inUser: function () {
var user = {
email: vm.email,
password: vm.password
};
return user;
}
}
});
RP.result.then(function()
{
//event.preventDefault();
},
function ()
{
vm.openConfirmCancelDB('sm');
});
};
openConfirmCancelDB() is the function that helps in opening the dialog box. The problem is how I can call preventDefault() function in order to get the current modal to stay in the backdrop while the dialog box appears on top of this modal. How can I go about accessing the event and its preventDefault function? Also, any other method that can help solve my problem is also fine with me.

Angular ui router, title dynamic

How I spend a parameter title of the post, to display the browser's title?
I use pageTitle parameter on my route, but if put directly: slug as a value, not works.
.state('posts',{
url : '/blog/:slug',
templateUrl : 'content/templates/single.html',
controller : 'SinglePostController',
data: {
pageTitle: 'title'
},
access: {
requiredLogin: false
}
})
The data : {} setting is static.
see similar:
Accessing parameters in custom data
If you want some dynamic feature use resolve : {}
Some links to examples and Q & A about resolve
Angularjs ui-router abstract state with resolve
EXTEND: A simple (really naive but working) example how to use resolve and $rootScope to manage browser title (check it here):
$stateProvider
.state('home', {
url: "/home",
templateUrl: 'tpl.html',
resolve: {
'title': ['$rootScope', function($rootScope){
$rootScope.title = "Other title";
}],
}
})
.state('parent', {
url: "/parent",
templateUrl: 'tpl.html',
resolve: {
'title': ['$rootScope', function($rootScope){
$rootScope.title = "Title from Parent";
}],
}
})
.state('parent.child', {
url: "/child",
templateUrl: 'tpl.html',
controller: 'ChildCtrl',
resolve: {
'titleFromChild': ['$rootScope', function($rootScope){
$rootScope.title = "Title from Child";
}],
}
})
And this could be the html
<!DOCTYPE html>
<html ng-app="MyApp" ng-strict-di>
<head>
<title>{{title}}</title>
Try it here
A challenge here is - what to do on navigation from child to parent, but it could be done by moving that setting into controller and work with $scope.$on('detsroy'...
Here is adjusted plunker
.state('parent.child', {
url: "/child",
templateUrl: 'tpl.html',
controller: 'ChildCtrl',
// no resolve, just controller fills the target
})
.controller('ChildCtrl', ['$rootScope', '$scope', function ($rootScope, $scope) {
var title = $rootScope.title;
$rootScope.title = "Title from Child";
$scope.$on('$destroy', function(){$rootScope.title = title});
}])

Route Angular to New Controller after Login

I'm kind of stuck on how to route my angular app to a new controller after login. I have a simple app, that uses 'loginservice'... after logging in, it then routes to /home which has a different template from the index.html(login page).
I want to use /home as the route that displays the partial views of my flightforms controllers. What is the best way to configure my routes so that after login, /home is the default and the routes are called into that particular templates view. Seems easy but I keep getting the /login page when i click on a link which is suppose to pass the partial view into the default.html template:
var app= angular.module('myApp', ['ngRoute']);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/login', {
templateUrl: 'partials/login.html',
controller: 'loginCtrl'
});
$routeProvider.when('/home', {
templateUrl: 'partials/default.html',
controller: 'defaultCtrl'
});
}]);
flightforms.config(['$routeProvider', function($routeProvider){
//sub pages
$routeProvider.when('/home', {
templateUrl: 'partials/default.html',
controller: 'defaultCtrl'
});
$routeProvider.when('/status', {
templateUrl: 'partials/subpages/home.html',
controller: 'statusCtrl'
});
$routeProvider.when('/observer-ao', {
templateUrl: 'partials/subpages/aobsrv.html',
controller: 'obsvaoCtrl'
});
$routeProvider.when('/dispatch', {
templateUrl: 'partials/subpages/disp.html',
controller: 'dispatchCtrl'
});
$routeProvider.when('/fieldmgr', {
templateUrl: 'partials/subpages/fieldopmgr.html',
controller: 'fieldmgrCtrl'
});
$routeProvider.when('/obs-backoffice', {
templateUrl: 'partials/subpages/obsbkoff.html',
controller: 'obsbkoffCtrl'
});
$routeProvider.when('/add-user', {
templateUrl: 'partials/subpages/users.html',
controller: 'userCtrl'
});
$routeProvider.otherwise({
redirectTo: '/status'
});
}]);
app.run(function($rootScope, $location, loginService) {
var routespermission=['/home']; //route that require login
$rootScope.$on('$routeChangeStart', function(){
if( routespermission.indexOf($location.path()) !=-1)
{
var connected=loginService.islogged();
connected.then(function(msg) {
if(!msg.data) $location.path('/login');
});
}
});
});
and my controllers are simple. Here's a sample of what they look like:
var flightformsControllers = angular.module('flightformsController', []);
flightforms.controller('fieldmgrCtrl', ['$scope','$http','loginService',
function($scope,loginService) {
$scope.txt='You are logged in';
$scope.logout=function(){
loginService.logout();
}
}]);
Any ideas on how to get my partials to display in the /home default.html template would be appreciated.
1) Move all the routing into the main app.config, and remove the duplicate route for /home.
2) change this line
var flightformsControllers = angular.module('flightformsController', []);
to
var flightforms = angular.module('flightforms', []);
3) change the app definition line to inject the flightforms module:
var app= angular.module('myApp', ['ngRoute', 'flightforms']);
That should get ya close.
For one of your comments, its a good idea to have an interecptor which catches any 401 un-authenticated errors from the server. This way, if a user's session expires before a route change, they will still have to login again to start a new session. Something like this in app.config should do it.
$provide.factory('logoutOn401', ['$q', '$injector', function ($q, $injector) {
return {
'responseError': function(response) {
if (response.status === 401) {
$location.path('/login')
return $q.reject();
} else {
return $q.reject(response);
}
}
};
}]);
$httpProvider.interceptors.push('logoutOn401');

Jquery Mobile when redirecting or changing url, pages does not have any css

I am working with a backbone, jquery mobile, express app. Everything looks fine when the app starts and works correctly, however, when I click a link or change the url the html renders correctly but no jquery mobile magic appears. It only renders in the login part with a header and footer and format, but when the url changes and I come back, the page loses its css or jquery mobile magic.
define(['views/index', 'views/register', 'views/login', 'views/forgotpassword', 'views/profile',
'views/vinbookDoc', 'models/Account', 'models/Vinbook', 'models/vinBooksCollection'],
function(IndexView, RegisterView, LoginView, ForgotPasswordView, ProfileView,
vinbookDocView, Account, Vinbook, vinBooksCollection) {
var AppRouter = Backbone.Router.extend({
currentView: null,
routes: {
"index": "index",
"login": "login",
"desk/:id": "desk",
"profile/:id": "profile",
"register": "register",
"forgotpassword": "forgotpassword",
"vinbook/:id": "showVinbook"
},
initialize: function(){
$('.back').live('click', function(event) {
window.history.back();
return false;
});
this.firstPage = true;
},
showVinbook: function(id) {
var getCollection = new vinBooksCollection();
getCollection.url = '/accounts/me/vinbook';
this.changeView( new vinbookDocView({
collection: getCollection,
id: id
}));
getCollection.fetch();
},
changeView: function(page) {
this.currentView = page;
$(this.currentView.el).attr('data-role', 'page');
this.currentView.render();
$('body').append($(this.currentView.el));
var transition = $.mobile.defaultPageTransition;
// We don't want to slide the first page
if (this.firstPage) {
transition = 'none';
this.firstPage = false;
}
$.mobile.changePage($(this.currentView.el), {changeHash:false, transition: transition});
},
index: function() {
this.changeView(new IndexView() );
},
desk: function (id){
var model = new Account({id:id});
this.changeView(new ProfileView({model:model}));
model.fetch({ error: function(response){ console.log ('error'+JSON.stringify(response)); } });
console.log('works');
},
profile: function (id){
this.changeView(new IndexView() );
},
login: function() {
this.changeView(new LoginView());
},
forgotpassword: function() {
this.changeView(new ForgotPasswordView());
},
register: function() {
this.changeView(new RegisterView());
}
});
return new AppRouter();
});
require
require.config({
paths: {
jQuery: '/js/libs/jquery',
jQueryUIL: '/js/libs/jqueryUI',
jQueryMobile: '/js/libs/jqueryMobile',
Underscore: '/js/libs/underscore',
Backbone: '/js/libs/backbone',
models: 'models',
text: '/js/libs/text',
templates: '../templates',
jqm: '/js/jqm-config',
AppView: '/js/AppView'
},
shim: {
'jQueryMobile': ['jQuery', 'jqm' ],
'jQueryUIL': ['jQuery'],
'Backbone': ['Underscore', 'jQuery', 'jQueryMobile', 'jQueryUIL'],
'AppView': ['Backbone']
}
});
require(['AppView' ], function(AppView) {
AppView.initialize();
});
login
define(['AppView','text!templates/login.html'], function(AppView, loginTemplate) {
window.loginView = AppView.extend({
requireLogin: false,
el: $('#content'),
events: {
"submit form": "login"
},
initialize: function (){
$.get('/login', {}, function(data){});
},
login: function() {
$.post('/login', {
email: $('input[name=email]').val(),
password: $('input[name=password]').val()
},
function(data) {
console.log(data);
if (!data.error){window.location.replace('#desk/me');}
}).error(function(){
$("#error").text('Unable to login.');
$("#error").slideDown();
});
return false;
},
render: function() {
this.$el.html(loginTemplate);
$("#error").hide();
return this;
}
});
return loginView;
});
Just some more details:
When I change from page or the url to another page, a flash of the rendered website appears and then the css or design disappears.
I think this can solve your problem:
$(document).bind('pagechange', function() {
$('.ui-page-active .ui-listview').listview('refresh');
$('.ui-page-active :jqmData(role=content)').trigger('create');
});