root html:
<html> stuff <div ui-view></div> stuff </html>
partial template
<div class="article-view">
{{date_published}}
</div>
When I navigate using $state.go('root.' + entryStateUrl); the url changes but new state's content (template) is appended right after root's state content. I need to show template on new clean page. How to do it?
Maybe similar to this SO.
Edit
I generated and attached states like this:
$stateProviderRef.state('root.' + generatedStateName,
{ url: 'root/' + generatedStateName,
templateUrl : 'partials/article-view.html',
controller: function($scope){
$scope.date_published = data.date_published;
}
});
UPDATE
When I changed it like this it stopped working:
$stateProviderRef.state(generatedStateName,
{ url: generatedStateName,
templateUrl : 'partials/article-view.html',
controller: function($scope){
$scope.date_published = data.date_published;
}
});
Redirecting to a new page means you won't be able to bind to the controller used from the origin page, since the redirected page won't have any attachment to your js code.
Related
I want to preload a template in my div using ui-router.
This is my template.html file which is located in /templates folder.
// its location is templates/template1.html
<div>
Template 1
</div>
The .config function in angularjs has the following code which includes the states. Here template1 is the child state of the state1
.state('state1',{
url:'/state1',
templateUrl:'templates/state1.html',
controller: 'state1Controller',
})
.state('state1.template1',{
templateUrl: 'templates/template1.html'
})
Template1 is loaded when i press a button, but i want the template to be preloaded. What can i do to attain my desired result?
Declarative way: Put all your template into a script tag with type as text/ng-template:
<script type="text/ng-template" id="templateId.html">
<p>This is the content of the template</p>
</script>
Code way: Use $templateCache for this.
In state1Controller, load your template and put it into cache like this:
$templateCache.put('templateId.html', 'This is the content of the template');
Or load it with http:
$http.get('templates/template1.html').then(function(template){
$templateCache.put('templateId.html', template);
})
Then in your router definition, put templateId.html as value of templateUrl
.state('state1.template1',{
templateUrl: 'templateId.html'
})
and any time you request templateId.html, angular will automatically find template in $templateCache before sending request to server.
Imagine some html as follows:
<body ng-app="blocksApp">
Some content goes here
<div ui-view="monty">
<div ui-view="dave">Aaa</div>
<div ui-view="pete">Bbb</div>
<div ui-view="steve">Ccc</div>
</div>
</body>
Using ui-router, is there any way to code a state that will set "dave" to a new snippet of html, whilst leaving everything else untouched.
e.g. I'd like to do this:
$stateProvider
.state('daveonly',{
url: "/dave",
views:{
'dave':{template:"Dave now has content"}
}
})
I can't get it to work. The reason I want to do this is that sometimes I'd like to replace 'Dave' with a partial update, other times I'd like to replace the entire 'monty' with a partial update. It seems that ui-router does not like having nested ui-views in the same snippet of html.
From one point of view I'd like to suggest:
move html code to '.tpl.html' files
use 'templateUrl' instead of 'template'
And check if the following is suitable for you:
$stateProvider.state("daveonly", {
views: {
"dave": {
templateUrl: 'daveonly.tpl.html',
},
"pete": {
templateUrl: 'pete.tpl.html',
},
"steve": {
templateUrl: 'steve.tpl.html',
},
}
});
Take a look at page1 and page2 for more details.
But from another point of view it could be more useful to use only one ui-view and to redesign current ui-views to become the appropriate directives with controllers/services: usage of directives with controllers/services could help to manage partial reload correctly and to write unit-tests.
Yes it can be done easily with the help of abstract states and yes you are correct ui-router doesn't like direct nested views directly but it works fine if the views are in any child template.
Now consider this main page(index.html)
<body ng-app="app">
<div ng-view=""></div>
</body>
Now this template which will appear in this unnamed view. (parent.html)
<h3>This is the parent template</h3>
<div ng-view="child1"></div>
<div ng-view="child2"></div>
Now the JS file
$stateProvide.state('home',{
url:'/',
abstract:true,
views:{
"":{
templateUrl:'parent.html'
}
}
})
.state('home.child',{
url:"",
views:{
'child1#home':{
templateUrl:'child1.html'
},
'child2#home':{
template:'Child2'
}
}
})
.state('home.child.child1',{
url:"child1#home.child",
views:{
'child1#home':{
templateUrl:'child1viewchange.html'
}
}
});
(Now the manipulation part)
(child1.html)
<button ui-sref="home.child.child1">Child</button>
Now child1viewchange.html pe jana padega and wo dekhne wali hai kaunsi kaisi thi/......
(child1viewchange.html)
<h3>Child1's view change</h3>
So now when we click on the button in child view1 the content in the first view changes and if we assign controllers then they can use them to control data.
I'm using Angular to build an SPA. There is only one ui-view in my app.
<section class="main-content" ng-class="{'menu-open': isSideNavOpen && !floatWithMenu}">
<div ui-view class="content-inner"></div>
</section>
And I defined several states:
$stateProvider
.state('home', {
reloadOnSearch: false,
url: '/home?tab',
templateUrl: AppInfo.assetPath + '/partials/workspaces/workspaces-default.html',
data: {
contentToken: AppInfo.CBAC.Welcome
}
})
.state('workspaces', {
reloadOnSearch: false,
url: '/workspaces?tab',
templateUrl: AppInfo.assetPath + '/partials/workspaces/workspaces-view.html',
data: {
contentToken: AppInfo.CBAC.Workspace.UsingWorkspace
}
})
They have nearly the same HTML:
<!-- workspaces-default.html -->
<div style="height:100%">
<x1-workspaces editable="false"></x1-workspaces>
</div>
<!-- workspaces-view.html -->
<div style="height:100%">
<x1-workspaces editable="true"></x1-workspaces>
</div>
The only difference is the attribute editable. If it's true, a function in x1WorkspacesCtrl (x1-workspaces directive controller) will run and queries DOM elements from it's template.
The problem, is that when url changes from /home to /workspaces, the old DOM is still in document while new DOM has been appended and fires x1WorkspacesCtrl. This makes document.querySelectorAll returns wrong collection.
I know I can fix it by using a more specific selector, such as "x1-workspaces[editable='true'] .workspaces". But I think it's quite dirty.
I'm wondering whether I could force remove old DOM from document before appending new DOM? I searched for a while and read the ui-router docs, but couldn't find an answer. Am I missing something?
You could inject $element into the controller. It would return the current element that the controller is attached to.
I am struggling to get nested states working with UI router
I want a page to view a device to be have a URL like /device/SERIAL_NUMBER/info where
/device is fixed
/SERIAL_NUMBER is variable aka :id
/info refers to a nested state
I have a number of nested states I want, but for simplicity I'm only showing a one state. Note that for info it shares the same controller as the parent view, other nested views do not.
State setup
.state('device', {
url: '/device/:id',
templateUrl: '/views/devices/device.html',
controller: 'viewDeviceController'
})
.state('device.info', {
url: 'info',
templateUrl: '/views/devices/device_info.html'
})
My main HTML looks something like this
<body>
<header><h1>Title</h1></header>
<div ui-view>
<!-- This is where /views/devices/device.html goes -->
</div>
/views/devices/device.html looks like so:
<div>General text about a device</div>
<div ui-view>
<!-- This is where /views/devices/device_info.html should go -->
</div>
If I navigate to /#/device/L340009 I see the main page and the device.html, I do not see device_info.html - this is expected but ideally I'd like the default to be to load the first route (info)
If I navigate to /#/device/L340009/info it redirects me to home (which is my otherwise) so something is wrong with the route
Where am I going wrong?
The url here should start with '/'
.state('device.info', {
// instead of this
// url: 'info',
// we need this
url: '/info',
templateUrl: '/views/devices/device_info.html'
})
that will support url concatenation
'/#/device/L340009' + '/info'
is '/#/device/L340009/info'
Hi I am working on a project using angularjs.
My roting logic is
.state( "authenticate", {
url: '/',
templateUrl : "views/login.html",
controller : "LoginCtrl",
data : {
requireLogin : false
}
})
.state( "beats", {
url: '/beats',
templateUrl : "views/beats.html",
controller : "BeatsCtrl",
data : {
requireLogin : true
}
})
.state( "outlets", {
url: '/outlets',
templateUrl : "views/beats.html",
controller : "BeatsCtrl",
data : {
requireLogin : true
}
})
I have ng-view in index.html that includes login.html first (url '/'). after login in each state I want to include a navbar in each template using ng-include.
currently I am writing in each page this line
<div ng-include=" 'templates/navbar.html' "></div>
but I want to include only once and each view should be render below it. But the problem is this navbar template itself getting render in ng-view.
and as far as I know we can not have multiple ng-view in one app.
can anyone please tell me what should be the best approach of doing this.
You could potentially have this nav bar included in the index.html itself, but hide it using ng-if or ng-show till the user is logged in. Once the user is logged in you could have a flag that evaluates to true and this nav bar can appear on every subsequent page.
in index.html
<div id="navbar" ng-if="isUserLoggedIn">
// nav bar code
</div>
And this 'isUserLoggedIn' will be set to true by your LoginCtrl on the scope.