Reputation: 655
I have an ng-include rendering partials on my page but as is the nature of ng-include I do not need a state to load the partials. I would like the URL to update when the ng-include updates its view so my analytics track it as a page change. I am wondering the best way to do this.
Also I am using angular-ui-router, which makes ng-include irrelevant because of nested states; until one comes across my situation: I have a large number of partials loading into the ng-include, which is lovely because all I need to provide is a path to the partial and not a massive number of different states to my $stateProvider file; but then there is no custom url. As such what I was wondering is the following:
Can an Ng-include update the page url when it loads a partial without having a state defined for that partial view
OR
something that would solve my problem altogether: is there a way to add states that have a url which can be dynamically updated? like:
.state( 'test', {
url: function( stateId ){
// where stateId is somehow passed into the $stateParams of the new state
},
templateUrl: "templates/views/test.html"
})
::JS::
// states
// self executing function
(function() {
var app = angular.module( 'app', [ 'ui.router', 'ngAnimate' ] );
app.config( function( $stateProvider, $urlRouterProvider ) {
// if url not defined redirect to login
$urlRouterProvider.when( '', "/home" );
// if nonexistant url defined redirect to sign-in
$urlRouterProvider.otherwise( "/home" );
// Now set up the states
$stateProvider
.state('home', {
url: "/home",
templateUrl: "templates/views/home.html"
});
}()); // self executing function end
// factory
//self executing container function
(function() {
var listFactory = function( ) {
// declare factory for return at end of function
var factory = {};
var list =
{
list1 : [
{
name: 'first',
url: 'templates/views/partials/view1.html',
id: '1'
},
{
name: 'second',
url: 'templates/views/partials/view2.html',
id: '2'
},
{
name: 'third',
url: 'templates/views/partials/view3.html',
id: '3'
},
{
name: 'fourth',
url: 'templates/views/partials/view4.html',
id: '4'
}
]
};
factory.getList = function(){
return list;
};
// return factory object to access data
return factory;
};
angular.module( 'app' ).factory( 'listFactory', listFactory );
}());
// controller
//self executing container function
(function() {
var listController = function ( $scope, listFactory ) {
$scope.listFactory = listFactory.getList();
// set a default list state
$scope.currentList = 'templates/views/partials/default.html';
// function sets list url on click to new scope item for rendering partial view
$scope.setCurrentList = function( url ) {
$scope.currentList = url;
};
};
listController.$inject = [ '$scope', 'listFactory' ];
angular.module('app')
.controller('listController', listController);
}());
::HTML::
<!-- this is loaded in the home state. -->
<div>
<div id="{{ list.id }}" ng-repeat="list in list.list1" ng-click="setCurrentList( list.url )">
<p>{{ list.name }}</p>
</div>
</div>
<div id="list-view-container">
<div class="rotateViewAnimate" ng-include src="currentList"></div>
</div>
::Rather irrelevant CSS::
/* Have to set height explicity on ui-view-container
to prevent collapsing during animation*/
#list-view-container {
position: relative;
min-height: 500px;
overflow: hidden;
}
/* rotate in / out animation transition */
.rotateViewAnimate.ng-enter, .rotateViewAnimate.ng-leave {
/* settings so animations display together */
position: absolute!important;
left: 0!important;
right: 0!important;
-webkit-transition: 0.5s ease-in-out all;
-moz-transition: 0.5s ease-in-out all;
-o-transition: 0.5s ease-in-out all;
transition: 0.5s ease-in-out all;
transform-style: preserve-3d;
}
.rotateViewAnimate.ng-enter {
transform: rotateY(90deg);
opacity: 0;
}
.rotateViewAnimate.ng-enter-active {
transform: rotateY(0deg);
opacity:1;
}
.rotateViewAnimate.ng-leave {
transform: rotateY(0deg);
opacity:1;
}
.rotateViewAnimate.ng-leave-active {
transform: rotateY(90deg);
opacity:0;
}
Upvotes: 1
Views: 12420
Reputation: 2139
the case is to change page URL after http create request (201) here's an example:
StudentsService.create($stateParams.sudId,studentInfo).then(r => {
$scope.newStudentId=r.data.id;
console.log(r.data, $scope.newStudentId);
$state.go("stateName", {sudId:$stateParams.sudId, id:$scope.newStudentId});
so, it will go to new student url after creating.
Upvotes: 0
Reputation: 655
The Issue I was looking to solve is gone over in some detail in the ui-router docs; found here:
https://github.com/angular-ui/ui-router/wiki
I used the following method to achieve the effect mentioned here:
"Set a Dynamic URL on a state using ui-router and angularJS"
Going through the code displayed in the question I will adjust it accordingly with my solution.
// states
// self executing function
(function() {
var app = angular.module( 'app', [ 'ui.router', 'ngAnimate' ] );
app.config( function( $stateProvider, $urlRouterProvider ) {
// if url not defined redirect to login
$urlRouterProvider.when( '', "/home" );
// if nonexistant url defined redirect to sign-in
$urlRouterProvider.otherwise( "/home" );
// Now set up the states
$stateProvider
.state('home', {
url: "/home",
templateUrl: "templates/views/home.html"
})
.state( 'home.urlChanger', {
url: '/urlChanger/name=:name&url=:url',
params: {
'spareParam' : 'whateverString'
},
views: {
'viewName@home': {
templateUrl: function ( $stateParams ){
return $stateParams.url;
},
controller: "mainController"
}
}
});
}()); // self executing function end
in the above state declaration the state "home.urlChanger" has a url with special characters which are given values from information passed to the $stateProvider variable. a VERY IMPORTANT note here is that if one wants to be able to access the item stored inside $stateParams it must be passed into the URL. as such, in my controller I use the following function to pass the information I want available in the state using the $state.go(); method as follows:
$scope.setParams = function( location ) {
var urlname = object.stored.in.factory.NAME,
url = object.from.factory.URL, // path to html file passed to be used in termplateurl from state
// set stateParams.name to be used in URL
$stateParams.name = urlName;
// set params to be passed into URL when $state.go(); is called, they will be available for use then and update the URL with the state setup from above.
$state.go( location, { name: $stateParams.name, url: url } );
};
as can be seen from the above example I tried storing into $stateparams.name in order to see if it would become available in stateparams, but as is expected when the state.go(); is called a new state is loaded and the previous $stateparams object is no longer available. hence why the information must be passed during $state.go in order to store it into the newly transitioned states $stateParams object.
so the html for causing this to occur could be an ng-click on any element that calls the setparams( location ) function, which will set your variables into $stateParams by passing them through the URL and making them available in your state ie: a dynamic URL set by the state itself.
hopefully someone finds that a bit helpful, it took me some time to work through myself.
Upvotes: 0
Reputation: 196
Alright so for partials when using Ui-Router you want to include a
<ui-view>
<i>Some content will load here!</i>
</ui-view>
where you want the partial to load.
Looks like you have the home state working correctly but if you want to nest the view you have to do something like this
.state('home.view1', {
url: '/notes',
templateUrl: 'pages/view1.html',
controller: 'mainController'
})
The full Url from doing this nested routing would be */#/home/notes For more info: https://github.com/angular-ui/ui-router/wiki
Upvotes: 2