Make two layouts share the same $scope - angularjs

I want to propose two layouts (ie, horizontal and vertical) for my contents. So switching in the selector will lead automatically to the corresponding layout. Here is the JSBin:
<html ng-app="flapperNews">
<head>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.2/angular-ui-router.js"></script>
<script type="text/ng-template" id="horizontal.tpl">
<textarea ng-model="one"></textarea>, <textarea ng-model="two"></textarea>
<br><br>{{one}}+{{two}}
</script>
<script type="text/ng-template" id="vertical.tpl">
<textarea ng-model="one"></textarea><br><textarea ng-model="two"></textarea>
<br><br>{{one}}+{{two}}
</script>
<script>
var app = angular.module('flapperNews', ['ui.router']);
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('entry', {
url: '/',
params: { tpl: 'vertical' },
templateUrl: function (params) {
return params.tpl + ".tpl"
}
})
}]);
app.controller('MainCtrl', ['$scope', '$state', function ($scope, $state) {
$scope.one = "one";
$scope.two = "two";
$scope.layouts = ["horizontal", "vertical"];
$scope.$watch('layout', function () {
$state.go('entry', {tpl: $scope.layout});
})
}])
</script>
</head>
<body ng-controller="MainCtrl">
<select ng-model="layout" ng-init="layout = 'horizontal' || layouts[0].value" ng-options="x for x in layouts"></select>
<br><br>
<ui-view></ui-view>
</body>
</html>
However, with the above code, each time we change the view, $scope.one and $scope.two are reset to their initial values. I would hope the change in their textarea would remain regardless of the change of layout.
Does anyone know how to solve this?

Easy sharing same data between different views by using factories (AngularJS factory documentation). Try this example, it uses a simple factory named myFactory to share data between controllers. This also does work on the same controller as in your case.
var myApp = angular.module("myApp",[ "ui.router"]);
myApp.config(function ($stateProvider, $urlRouterProvider){
$stateProvider.state("state1", {
url: "#",
template: '<p>{{ aValue }}</p><button ng-click="bindValue(\'its me\')">Bind value</button>',
controller: "myController"
}).state("state2", {
url: "#",
template: '<p>{{ aValue }}</p><button ng-click="bindValue(\'its me\')">Bind value</button>',
controller: "myController"
});
});
myApp.controller( "myController", function($scope, myFactory) {
$scope.aValue = myFactory.myValue;
$scope.bindValue = function (value) {
$scope.aValue = value;
myFactory.myValue = value;
}
});
myApp.factory('myFactory', function () {
return {
myValue: ''
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js"></script>
<div ng-app="myApp">
<nav>
<a ui-sref="state1">State 1</a>
<a ui-sref="state2">State 2</a>
</nav>
<div ui-view></div>
</div>

I think that you should use nested views - you can define main controller on parent route state and define two nested states corresponding to two views. This way parent controller will remain (it's not re-initialised when child states are switched) and only nested states views will be changed. Something like this:
$stateProvider
.state('myState', {
url: '/test/',
template: '<div ui-view></div>',
controller: function() {
//main controller shared by child states
...
}
})
.state('myState.view1', {
url: '/test/view1'
templateUrl: 'tpl-1.hmtl',
...
})
.state('myState.view2', {
url: '/test/view2'
templateUrl: 'tpl-2.hmtl',
...
})

Related

AngularJS routing issue

Here, I want to print 'Nerve Center Dashboard' when route is '/' ,'Consumption Dashboard' for '/consumption' and same for every route in <p> tag. Please help
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular-route.js"></script>
<script src="assets/jquery-1.12.4.min.js" type="text/javascript"></script>
<script src="assets/bootstrap-3.3.7/js/bootstrap-3.3.7.min.js" type="text/javascript"></script>
</head>
<body ng-app="myapp">
<p></p> /------------*text to be printed*-------------/
<ul class="nav nav-tabs">
<li onclick="dashboardTitle('Nerve Center Dashboard')" id="nerve">Nerve Center
</li>
<li onclick="dashboardTitle('Consumption Dashboard')" id="consumptionn">Consumption Analysis
</li>
<li onclick="dashboardTitle('Fulfillment Dashboard')" id="fulfillmentt">Fulfillment Analysis
</li>
<li onclick="dashboardTitle('Inventory Dashboard')" id="inventoryy">Inventory Analysis
</li>
</ul>
<div class='col-xs-12 rmpm' style='height:auto;'>
<div ng-view></div>
</div>
<script>
var myApp = angular.module('myApp', ['ngRoute']);
//routing for tabs
myApp.config(['$routeProvider',
function($routeProvider) {
// $locationProvider.html5Mode(true);
$routeProvider.
when('/', {
templateUrl: 'nervecenter.html',
controller: 'nervecenterController'
}).
when('/fulfillment', {
templateUrl: 'fulfillment.html',
controller: 'fulfillmentController'
}).
when('/consumption', {
templateUrl: 'consumption.html',
controller: 'consumptionController'
}).
when('/inventory', {
templateUrl: 'inventory.html',
controller: 'inventoryController'
}).otherwise({
templateUrl: 'nervecenter.html'
});
}
]);
</script>
</body>
</html>
You just have to create a global variable in angular's scope to initialize the <p> tag based on URL. Initialise the variable in each of the controllers with the desired value. You also have to create a main controller that will be in the scope of <p> tag, so that any initialization on $rootScope will reflect under this main controller.
Main Controller:
var myApp = angular.module('myApp', []);
myApp.controller('mainController', ['$scope','$rootScope' function ($scope,$rootScope) {
});
}]);
First Controller:
myApp.controller('nervecenterController', ['$scope','$rootScope' function ($scope,$rootScope) {
$rootScope.title="Nerve Center Dashboard"
});
}]);
Second Controller:
myApp.controller('consumptionController', ['$scope','$rootScope' function ($scope,$rootScope) {
$rootScope.title="Consumption Dashboard"
});
}]);
HTML:
<body ng-app="myapp" ng-controller="mainController">
<p>{{title}}</p>
Working Plunker: https://plnkr.co/edit/xmLZvHK57GpaIFsHzvvV?p=preview

Switch among different templates/views

I want to propose two layouts (ie, horizontal and vertical) for my contents. So switching in the selector will lead automatically to the corresponding layout. My current JSBin cannot accomplish this switching:
<html ng-app="flapperNews">
<head>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.2/angular-ui-router.js"></script>
<script type="text/ng-template" id="horizontal.tpl">
{{one}}, {{two}}
</script>
<script type="text/ng-template" id="vertical.tpl">
{{one}}<br>{{two}}
</script>
<script>
var app = angular.module('flapperNews', ['ui.router']);
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('entry', {
url: '/',
templateUrl: "vertical.tpl"
})
}]);
app.controller('MainCtrl', ['$scope', '$state', function ($scope, $state) {
$scope.one = "one";
$scope.two = "two";
$scope.layouts = ["horizontal", "vertical"];
$scope.$watch('layout', function () {
$state.go('entry'); // need to amend this such that changing "layout" leads to different template
})
}])
</script>
</head>
<body ng-controller="MainCtrl">
<select ng-model="layout" ng-options="x for x in layouts"></select>
<br><br>
<ui-view></ui-view>
</body>
</html>
Additionally, I hope the solution would NOT display the layout information in the URL; users can only see and choose layout in the web page. Moreover, I don't want a solution by SHOWING/HIDING <ui-view="horizontal"></ui-view>" or <ui-view="vertical"></ui-view> based on the selection. I would prefer a solution that passes layout information to states to choose the corresponding template (but without disclosing it in URL).
Does anyone know how to do this?
Use a non-url parameter such as layout.
Choose the template using a templateUrl function.
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('entry', {
url: '/',
params: { layout: 'vertical' },
templateUrl: function(params) {
return params.layout + ".tpl";
}
})
}]);
then you can switch using state.go or ui-sref
ui-sref="entry({ layout: 'horizontal' })"

change page title in ui-router not work

i try to change my page title in angular app use ui router
i found this demo and its work fine https://plnkr.co/edit/NpzQsxYGofswWQUBGthR?p=preview
but when i attempt to try the same demo not work i need to find issue that make my demo not work https://plnkr.co/edit/pqumJL?p=preview
why demo not change page title although it's work in demo
try this :
(function () {
'use strict';
angular
.module('app', ['ui.router'])
.config(config)
config.$inject = ['$stateProvider', '$urlRouterProvider', '$urlMatcherFactoryProvider'];
function config($stateProvider, $urlRouterProvider, $urlMatcherFactoryProvider) {
$urlRouterProvider.otherwise('/home');
$urlMatcherFactoryProvider.caseInsensitive(true);
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'home.view.html',
data: {
pageTitle: 'Home'
}
})
.state('about', {
url: '/about',
templateUrl: 'about.view.html',
data: {
pageTitle: 'About'
}
})
}
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<script src="https://code.angularjs.org/1.3.3/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.11/angular-ui-router.min.js"></script>
<script src="app.js"></script>
<script src="app-directives/title-directive.js"></script>
<title>{{title}}</title>
</head>
<body>
<div class="panel" ui-view></div>
<ul class="nav navbar-nav">
<li>
<a ui-sref="home" ui-sref-active="activeState">Home</a>
</li>
<li>
<a ui-sref="about">About</a>
</li>
</ul>
</body>
</html>
https://plnkr.co/edit/JifcOKrUC9tBfV8jY5ko?p=preview
In plunkr you just have to replace
<script src="app-directives/title-directive.js"></script>
by
<script src="title-directive.js"></script>
I can provide you a better way to do so:
link: function (scope, element, attrs) {
var defaultTitle = element.text();
if (element[0].tagName === 'TITLE') {
var listener = function (event, toState) {
var title;
if (toState.data && toState.data.pageTitle) {
if(toState.data.placeholder && toState.data.placeholder.title)
title = toState.data.pageTitle, toState.data.placeholder.title;
else
title = toState.data.pageTitle;
} else if (defaultTitle) {
title = defaultTitle;
} else {
title = 'No title';
}
$timeout(function () {
element.text(title);
}, 0, false);
};
$rootScope.$on('$stateChangeSuccess', listener);
}
}
Thanks the problem solved
there is an error in ui router script and incompatible version
when use online version the problem solved
thanks all

how to add routing using angular-ui-router?

I am new to angularjs ,i make a sample app with custom directives now i add routing as well but it doesn't working.When i start project nothing is displayed in browser.
here is my index.html:
<html ng-app="myApp">
<head>
<title>Reddit New World News (Task)</title>
<link href='http://fonts.googleapis.com/css?family=Varela+Round' rel='stylesheet' type='text/css'>
<script src="angular/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js"></script>
<script src="myApp.js"></script>
<script src="myAppCtrl.js"></script>
<script src="routes.js"></script>
<script src="headerDirective.js"></script>
<script src="searchDirective.js"></script>
<script src="myDataDirective.js"></script>
</head>
<body>
<div ng-view></div>
</body>
</html>
myAppCtrl:
// TODO: Wrap in anonymous function
(function () {
var myApp = angular.module('myApp', ['ui.router']);
// TODO: min-safe with bracket notation
myApp.controller('myAppCtrl', ['$scope', '$http', function($scope, $http) {
$scope.sortType = '';
$scope.sortReverse = true;
// TODO: Keep lines short - it's easier to read
$http.get("https://www.reddit.com/r/worldnews/new.json")
.success(function (response) {
$scope.stories = response.data.children;
});
}]);
myApp.controller('aboutController',function(){
// create a message to display in our view
$scope.message = 'Everyone come and see how good I look!';
});
myApp.controller('contactController', function($scope) {
$scope.message = 'Contact us! JK. This is just a demo.';
});
})();
headerDirective.html:
<div class="top-header"></div>
<div class="container">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="header">
<h1>Reddit</h1>
</div>
<div class="header-right">
<h2>World's Latest News</h2>
</div>
<div>
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>
</div>
</nav>
<div class="clearfix"></div>
</div>
routes.js:
angular.module('myAppCtrl')
.config(['$stateProvider', '$locationProvider', '$urlRouterProvider',
function ($stateProvider, $locationProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/index.html');
// See route.webapp.js for allowed routes
$stateProvider
.state('app', {
templateUrl: '/templates/app.html',
controller: 'myAppCtrl',
abstract: true
})
.state('app.home', {
url: '/home',
templateUrl: '/templates/index.html',
controller: 'myAppCtrl'
})
.state('app.about', {
url: '/about',
templateUrl: '/templates/about.html',
controller: 'aboutController'
})
.state('app.contact', {
url: '/contact',
templateUrl: '/templates/contact.html',
controller: 'contcatController'
});
$locationProvider.html5Mode(true);
}
]);
})();
any guide thanks.
First there is a problem with your config block :
myApp.config(...)
not
angular.module('myAppCtrl').config(...);
Else you're redeclaring a new module. That doesn't make sense. You mix up controllers and module, that's two different things.
Then you have to change some things in your HTML file :
If you're using UI-Router it's :
<div ui-view></div>
not like ngRouter :
<div ng-view></div>
Then you're using $locationProvider.html5Mode(true);
So you have to configure your server to emulate paging, see doc.
Finally you have to add the base href of your angular application in the <head> tag like that :
<base href="/">

Switching Angular view not updating variables

I'm just building out a simple app to learn AngularJS and having trouble updating variables when switching views. Here's what I have so far:
function routeConfig($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/',
templateUrl: 'app/main/main.html',
controller: 'MainController',
controllerAs: 'main'
})
.state('team', {
url: '/team',
templateUrl: 'app/main/team.html',
controller: 'MainController',
controllerAs: 'main'
})
$urlRouterProvider.otherwise('/');
}
Here's part of my controller:
function MainController($timeout, webDevTec, toastr, $resource, $scope) {
var vm = this;
var GetTeam = $resource('https://apisite.com/api_endpoint/:teamId', {teamId: '#id'});
vm.teamName = '';
function getTeamInfo(id) {
var teamObj = GetTeam.get({teamId: id});
$timeout(function(){
vm.teamName = teamObj["name"];
},100)
};
vm.getTeamInfo = getTeamInfo;
}
Then in my main.html I call getTeamInfo with a ng-click:
<ul class="list-group">
<li class="list-group-item" ng-repeat="team in main.teams" ng-click="main.getTeamInfo(team.id)">{{ team.name }}</li>
</ul>
Clicking on that link will take you to team.html:
<div class="row">
<div class="col-sm-12">
<h3>{{ main.teamName }}</h3>
<ul class="list-group">
. . .
</ul>
</div>
</div>
For some reason "main.teamName" is not updating. I've tried the $scope.$apply(function(){vm.teamName = teamObj["name"]} approach as well with no luck. I also did 'console.log(teamObj["name"])' before vm.teamName and 'console.log(vm.teamName)' after to see if I get the expected results and I do. I just have no idea now why it's not updating the new view.
Thank you for your insight, patience, and time!
UPDATE 1
I also tried using $scope on my variables ($scope.teamName) and using $scope.$apply(function(){$scope.teamName = teamObj["name"]}) with no luck.
UPDATE 2
I also tried called $scope.$apply(); after 'vm.teamName = teamObj["name"]' with no luck
It looks like teamObj is not populated yet at the point when you assign vm.teamName
You would make your life so much easier if you just reference teamObj rather than creating a new property.
I made a plunker based on a modified version of your code to show a possible implementation. I couldn't get it to work using the controllerAs syntax and I'm not entirely sure why (possibly because of some issues related to sharing a controller; not sure). Anyway, hopefully it will be of some help to you.
DEMO
app.js
var app = angular.module('plunker', ['ui.router', 'ngResource']);
app.controller('MainController', MainController);
app.config(routeConfig);
function MainController($timeout, $scope, $resource) {
// mock data
var GetTeam = $resource('http://demo7592070.mockable.io/teams/:teamId', {teamId: '#id'});
//var GetTeam = $resource('https://apisite.com/api_endpoint/:teamId', {teamId: '#id'});
$scope.teamName = 'undefined';
$scope.getTeamInfo = getTeamInfo;
function getTeamInfo(id) {
var teamObj = GetTeam.get({teamId: id});
$scope.teamName = teamObj.name;
$scope.teamObj = teamObj;
};
}
function routeConfig($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/',
templateUrl: 'main.html',
controller: 'MainController'
})
.state('team', {
url: '/team',
templateUrl: 'team.html',
controller: 'MainController'
});
console.log('ROUTECONFIG');
$urlRouterProvider.otherwise('/');
}
index.html
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<!-- JS (load angular, ui-router, and our custom js file) -->
<script src="http://code.angularjs.org/1.2.13/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.2/angular-resource.js"></script>
<script src="app.js"></script>
</head>
<body>
<a ui-sref="home">home</a>
<a ui-sref="team">team</a>
<div ui-view=""></div>
</body>
</html>
main.html
<h1>Home</h1>
<pre>$scope.teamName => {{teamName}}</pre>
<pre>$scope.teamObj => {{teamObj}}</pre>
<pre>$scope.teamObj.name => {{teamObj.name}}</pre>
<button ng-click="getTeamInfo(1)">Get Team 1</button>
team.html
<h1>Team</h1>
<pre>$scope.teamName => {{teamName}}</pre>
<pre>$scope.teamObj => {{teamObj}}</pre>
<pre>$scope.teamObj.name => {{teamObj.name}}</pre>
<button ng-click="getTeamInfo(2)">Get Team 2</button>

Resources