Angular UI update route with different parameters - javascript

Using Angular UI router, I have a route set up as follows
$stateProvider.state('edit', {
url: '/:file/:page',
...
}
if I change the route from /edit/file1/page1 to /edit/file1/page2, the view doesn't refresh. I'm calling $state.go, and I can easily redraw the page, but by not running this through the router things like the back button don't update the route.
Can someone advise how to update the route so the view is updated?
Thanks.

If I understand your intention here, it is to have your templateUrl be based on the :file and :page $stateParams.
Since you haven't shown how you are actually using $state.go, I put together an example that shows a few of the ways you can change between states with and without { reload: true }.
angular.module('exampleApp', ['ui.router'])
.config(function($urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise('/file1/page1');
$stateProvider
.state('edit', {
url: '/:file/:page',
controller: 'FilePageCtrl',
templateUrl: function($stateParams) {
return $stateParams.file + "-" + $stateParams.page + ".html";
}
});
})
.controller('FilePageCtrl', function($scope, $state) {});
Here are some example links that change the state (but will not re-run the controller and template if it's already the current state):
<a ui-sref="edit({ file: 'file1', page: 'page2' })">/file1/page2</a>
Is more or less the same as (whether inline with ng-click or within a controller):
<a href ng-click="$state.go('edit', { file: 'file1', page: 'page2' })">/file1/page2</a>
The following two will force the controller and templateUrl to run, regardless if the current state is the same:
<a ui-sref="edit({ file: 'file1', page: 'page2' })" ui-sref-opts="{ reload: true }">/file1/page2</a>
<a href ng-click="$state.go('edit', { file: 'file1', page: 'page2' }, { reload: true })">/file1/page2</a>
You can read more about using a dynamic templateUrl here: https://github.com/angular-ui/ui-router/wiki#templates
Here is a working example: http://plnkr.co/edit/JUgUB3I675Kh7kKkitgJ?p=preview

Related

angular uirouter opens wrong url

I'm new to Angular 1 and have to implement a new feature on an existing webapp. The app uses jhipster to generate some parts of the backend and frontend (Angular 1 and uirouter).
So I tried to use my own route and state like this which is mostly copy and pasted from existing components of the webapp:
(function() {
'use strict';
angular
.module('artemisApp')
.config(stateConfig);
stateConfig.$inject = ['$stateProvider'];
function stateConfig($stateProvider) {
$stateProvider
.state('model-comparison-exercise-for-course', {
parent: 'entity',
url: '/course/{courseid}/model-comparison-exercise',
data: {
authorities: ['ROLE_ADMIN', 'ROLE_TA'],
pageTitle: 'artemisApp.modelComparisonExercise.home.title'
},
views: {
'content#': {
templateUrl: 'app/entities/model-comparison-exercise/model-comparison-exercise.html',
controller: 'ModelComparisonExerciseController',
controllerAs: 'vm'
}
},
resolve: {
translatePartialLoader: ['$translate', '$translatePartialLoader', function ($translate, $translatePartialLoader) {
$translatePartialLoader.addPart('modelComparisonExercise');
$translatePartialLoader.addPart('exercise');
$translatePartialLoader.addPart('global');
return $translate.refresh();
}],
courseEntity: ['$stateParams', 'Course', function ($stateParams, Course) {
return Course.get({id: $stateParams.courseid}).$promise;
}]
}
});
}
})();
Then I try to open this route with the following code:
<a ui-sref="model-comparison-exercise-for-course({courseid:course.id})"
data-translate="artemisApp.course.modelComparisonExercises"></a>
By clicking on that link a http get request is fired which returns a http status code 404: http://localhost:8080/app/entities/model-comparison-exercise/model-comparison-exercise.html
Actually, the url that should be opened is http://localhost:8080/#/course/1/model-comparison-exercise
Any idea what I could have configured wrong?
Please try changing 'content#' to 'content#artemisApp'.
As explained here:
The symbol before the # is the name of the view you want to match, and the symbol after the # is a reference to the state in which the template the ui-view directive should exist in.
And the <a> tag is not being closed:
<a ui-sref="model-comparison-exercise-for-course({courseid:course.id})"
data-translate="artemisApp.course.modelComparisonExercises"></a>
Searching through the code, I found that model-comparison-exercise.html does not exist in folder model-comparison-exercise. Besides model-comparison-exercises.html exist.

URL Routing to Child View

I have setup a parent view with multiple child views, and it seems to be working with no problem in the application. The problem is if you refresh the page or try to go directly to the child view with the appropriate url.
Here are my states that I am loading. This the parent state:
{name: "myTeam", url: "/myTeam", template: "<my-team></my-team>"}
Here's one of the children:
{name: "myTeam.info", url: "/info", template: "<my-team.info></my-team.info>"}
Here's another:
{name: "myTeam.checkin", url: "/checkin/{book}/{club}/{team}/{bus}", template: "<my-team.checkin></my-team.checkin>"}
So, if I visit the Info view, it loads the template correctly and sets the url to "/myTeam/info". If try to refresh the page or just start out at the url "/myTeam/info", it won't load the state/template.
I added code to the angular-ui-router.js (version 0.1.2) to try to debug. I added the console.log() line at line 912.
UrlMatcher.prototype.exec = function (path, searchParams) {
var m = this.regexp.exec(path);
console.log(" --> " + this.regexp + " -- " + path + " = " + m);
if (!m) return null;
searchParams = searchParams || {};
Here's the output:
--> /^\/myTeam\/?$/ -- /myTeam/info = null
--> /^\/info(.*)?\/?$/ -- /myTeam/info = null
--> /^\/checkin\/([^\/]*)?\/([^\/]*)?\/([^\/]*)?\/([^\/]*)?(.*)?\/?$/ -- /myTeam/info = null
So, it's not matching on the parent or the child.
I was following the example on the Nested States and Nested Views. Their urls looked the same to me.
I don't see how it makes a difference, but I am using the UI extras to load these as future states and using the ocLazyLoad.
Any thoughts on how I can get the URL to work? Or, how it is supposed to work?
I finally determined that the problem was with the UI Extras and future state loading.
I ended out taking the easy road for time's sake. I changed my project to not use any child states, and that takes care of my problem.
From the best I can tell, it is not loading all of the children states. The future state loader is only matching the parent and loading the parent.
I think my problem is similar to this problem that I found here:
UI Router Extras Issue #63
I attempted to write code in my future state loader that would load the parent state and all of it's children. That forced me to have to modify the UI Router Extras to accept an array of promises, and I had to modify too many things to make it work.
Hopefully, at some point I can try to build a more complete fix outside my project and contribute it, but for now, my solution is to avoid child states.
weird, my project have children states, and some children have more children states too, and it's working fine without problems, i will show you how i setup my url:
dashboardState.js
the state with url: '' is the home page, and it is loaded when you navigate to url /home, but their children home loads inside dashboard.
(function () {
'use strict';
angular
.module('myapp')
.config(dashboardStates);
function dashboardStates($stateProvider) {
var dashboard = {
name: 'dashboard',
abstract: true,
url: '/home', // view inicial abaixo
templateUrl: 'app/components/Dashboard/view/dashboard.html',
controller: 'DashboardController',
controllerAs: 'dashboard'
};
var dashboardHome = {
name: 'dashboard.home',
url: '',
parent: 'dashboard',
templateUrl: 'app/components/Dashboard/view/dashboard.home.html',
controller: 'DashboardController',
controllerAs: 'home',
ncyBreadcrumb: {
label: 'Home'
}
};
// states
$stateProvider
.state(dashboard)
.state(dashboardHome);
}
}());
and the state below loads inside the dashboard view:
profileState.js
(function () {
'use strict';
angular
.module('myapp')
.config(profileStates);
function profileStates($stateProvider) {
var profile = {
name: 'dashboard.profile',
url: '/profile',
templateUrl: 'app/components/Profile/view/profile.html',
controller: 'ProfileController',
controllerAs: 'profile'
};
var profileEdit = {
name: 'dashboard.profile.edit',
url: '/edit',
templateUrl: 'app/components/Profile/view/profile.edit.html',
controller: 'ProfileController',
controllerAs: 'profile'
};
$stateProvider
.state(profile)
.state(profileEdit);
}
}());
more info: https://github.com/angular-ui/ui-router/wiki/Nested-States-and-Nested-Views

changing the view of the div using angular ui-router

Here is the code which i have written so as to change my view (without any change in the url)
<a ui-sref="chat.menu" ng-click="click1();">Latest</a>
<a ui-sref="chat.menu" ng-click="click2();">Mail</a>
<div ui-view="{{item}}"></div>
var app = angular.module('myApp',['ui.router'])
.run(['$rootScope','$state','$stateParams', function($rootScope,$state,$stateParams){
$rootScope.$state = $state;
$state.$stateParams = $stateParams;
}]);
app.config(function($stateProvider,$urlRouterProvider){
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home',{
url:'/',
templateUrl:'templates/main.html',
})
.state('chat',{
url:'/chat',
templateUrl:'templates/chatPage.html',
controller: 'chatController',
})
.state('chat.menu',{
views: {
'':{
template: '<h1>Blank</h1>',
},
'latest': {
template: '<h1>Latest</h1>',
},
'mail': {
template: '<h1>Mail</h1>',
}
}
});
});
app.controller('Controller', function($scope,$state, authentication){
$scope.item='';
$scope.click1 = function(){
$scope.item = "latest";
}
$scope.click2 = function(){
$scope.item = "mail";
}
});
Its working fine, but the problem is that I change the the view only once. Once a view is loaded in the ui-view, then another view is not getting loaded in it on the click of the button.
All i want is that, when the user click the button the view should be changed according to the click of the button without any change in the url.
So I'd trying something like this: having two states instead of one. If you want to keep only one state, you'd need to pass parameters to that state, but for a simple example like this, two states will work just fine:
myApp.config(function ($stateProvider){
$stateProvider
.state("latest", {
url: "#",
template: "<h1>Latest</h1>",
controller: "Ctrl1"
})
.state("mail", {
url: "#",
template: "<h1>Mail</h1>",
controller: "Ctrl2"
});
});
What we are doing here is either setting the URL to the same in both states, or setting no URL at all. Also, if you want to assign controllers to your views, here is were we do it. You can assign no controllers, two different controllers, or the same controller if you would like.
Then setup your view like this:
<nav>
<a ui-sref="latest">Latest</a>
<a ui-sref="mail">Mail</a>
</nav>
<div ui-view></div>
Here is a working JSFiddle

Multiple views to nested state

I am using ui-router and I try to create several views inside one of my nested states.
In my logic, all of the views should be visible whenever the parent state is active.
I have read the wiki page on multiple named views multiple times, but could not get anything working yet.
My state template would show up, but my views never do.
Here is a working plunker
(You have to click on "Followers" in the navbar for the view to show up. Haven't figured why yet).
Important parts are the config
app.config([
'$stateProvider',
'$urlRouterProvider',
function ($stateProvider, $urlRouterProvider){
$stateProvider
.state('dashboard', {
url: '/dashboard',
templateUrl: 'dashboard.html',
controller: 'DashboardCtrl',
authenticate: true
}).state('dashboard.followers', {
url: '/followers',
templateUrl: 'dashboard.followers.html',
controller: 'DFollowersCtrl',
authenticate: true
}).state('dashboard.followers.add', {
views: {
'add': {
templateUrl: 'dashboard.followers.add.html',
controller: 'DFollowersAddCtrl',
authenticate: true
}
},
});
$urlRouterProvider.otherwise('dashboard');
}
]);
The main dashboard template (level 2, using a generic ui-view)
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<div class="flash-area">
<flash-message duration="2000" show-close="true"></flash-message>
</div>
<ui-view></ui-view>
</div>
and the dashobard.followers specific level 3 view, that has a specific name
<div>
<h1 class="page-header">Followers</h1>
<div ui-view="add"></div>
</div>
The trick is coming from, I think, a combination of :
I want to use level 3 nesting
Level 2 uses a generic ui-view, because it may contains my dashboard or something else.
Level 3 contains specific views, as it is where I want to use "views" and not "states" (as far as I understood, at least).
The final aim is to have more than one view in my template, but for now I reduced the attempts to only show the 'add' view.
I have seen several similar questions on SO already, such as this one or this other one but so far my attempts have not been fruitful.
I can access my "add" view directly if I reach its URL (when I try setting one)
But the dashboard.followers state does not get populated by the views.
I think there are several mistakes here you made:
if you want the url of dashboard.followers state and dashboard.followers.add state to be same, the child state dashboard.followers.add does not need the url option
probably can be a mistake(I am not sure because no code is provided), if you don't use the
views: { ... }
named views, but just directly use
url: '/followers',
templateUrl: '/partials/dashboard.followers.html'
angular just assume you want to insert the template in an unnamed <div ui-view></div> in the parents state's template not the root template. for example, in my example code, for state dashboard.followers, since it is a child state of dashboard, if I want to insert the template in root html template, I have to use
views: {
'#': {
template: '<div><h1 class="page-header">Followers</h1><a ui-sref="dashboard.followers.add">add</a><div ui-view="add"></div></div>'
}
}
/* myApp module */
var myApp = angular.module('myApp', ['ui.router'])
.config(['$stateProvider', function($stateProvider) {
$stateProvider
.state('landing', {
url: '/',
template: '<p>landing</p><a ui-sref="dashboard">dashboard</a>'
})
.state('dashboard', {
url: '/dashboard',
template: '<p>landing</p><a ui-sref="dashboard.followers">followers</a>'
})
.state('dashboard.followers', {
url: '/followers',
views: {
'#': {
template: '<div><h1 class="page-header">Followers</h1><a ui-sref="dashboard.followers.add">add</a><div ui-view="add"></div></div>'
}
}
})
.state('dashboard.followers.add', {
views: {
'add': {
template: '<p>followers</p>'
}
}
});
}])
.controller('MyAppCtrl', function($scope, $state /*, $stateParams*/ ) {
$state.go("landing");
});
<body ng-app="myApp" ng-controller="MyAppCtrl">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.js"></script>
<div ui-view></div>
</body>
update
I made two plunkers to fit two different situation:
if you want to dynamically load add state to ui-view="add" by a
link, check
this out.
if you just want a sub template to be loaded always on dashboard.followers state, simply remove add states, and use views: {...} to load the add template in. here is the plunker.

ui.router changing state, but ui-view doesn't display anything?

Though the states are changing successfully, I can't get the ui-view to update:
HTML
<a ui-sref="promo.foo">Foo state</a>
<a ui-sref="promo.bar">Bar state</a>
<div ui-view=""></div>
JavaScript
$urlRouterProvider.otherwise("/");
$stateProvider
.state('promo', {
url: "/",
abstract: true
})
.state('promo.foo', {
url: "promo/foo",
template: "'<h3>Foo</h3>'",
controller: function($scope) {
$scope.value = 'foo';
}
})
.state('promo.bar', {
url: "promo/bar",
template: "'<h3>Bar</h3>'",
controller: function($scope) {
$scope.value = 'bar';
}
})
Plnkr (with bootstrap styling)
I have also tried setting ui-view to equal specific states also; and to dynamically change its RHS from my $scope.
Since you're trying to create nested views, the home state should have a template with an ui-view-element in it.
Also you have both double and single quotes in the template
template: "'<h3>Foo</h3>'"
Is this Plunker what you had in mind?
Give your abstract state a template containing inside which your sub states will render ... eg http://scotch.io/tutorials/javascript/angular-routing-using-ui-router

Categories

Resources