I would like to disable modal dialogs in a jhipster generated application in favor of elements displayed in page.
See https://github.com/jhipster/generator-jhipster/issues/2693
You should make it just like the "-detail" state right above. Make a block like
views: {
'content#': {
templateUrl: 'app/entities/smthn/smthn-dialog.html',
controller: 'SmthnDialogController',
controllerAs: 'vm'
}
},
after data object and move resolve out of the $uibModal.open.
Then there is a bit of change in your controller.
Make clear function look like that:
function clear () {
$state.go('^');
}
and replace $uibModalInstance.close(result); with $state.go('smthn', {}, { reload: 'smthn' }); in onSaveSuccess.
Related
I'm new to Ionic and AngularJS so I'm struggling with (hopefully) something simple. I have these two states:
.state('menu', {
url: '/mobile/beer',
controller: 'beerCtrl',
templateUrl: 'templates/beer-menu.html'
})
.state('detail', {
url: '/mobile/beer/:id',
controller: 'beerDetailCtrl',
templateUrl: 'templates/beer.html',
resolve: {
beer: function($stateParams, beerService) {
return beerService.findBeerById($stateParams.id)
}
}
})
The 'menu' state fetches all beers from a server and hand the list over to 'beer-menu.html' that contains an ion-list to display the list. When the user selects a beer in the list, the 'detail' states steps in to display more details about the beer.
It's all working but I want to improve it a bit by using an abstract state:
.state('beer', {
abstract: true,
url: '/mobile/beer'
})
.state('beer.menu', {
url: '',
controller: 'beerCtrl',
templateUrl: 'templates/beer-menu.html'
})
.state('beer.detail', {
url: '/:id',
controller: 'beerDetailCtrl',
templateUrl: 'templates/beer.html',
resolve: {
beer: function($stateParams, beerService) {
return beerService.findBeerById($stateParams.id)
}
}
})
It looks totally OK to me - esp because this is based on one of the 'Formulas' from the Ionic Framework website. Nevertheless the app stops working when I structure the states like that. I've tried to tweak it in various way but couldn't get it working. Do you see what's wrong?
As the UI-Router documentation you have to define also a template for abstract state 'beer':
Remember: Abstract states still need their own <ui-view/> for their children to plug into. So if you are using an abstract state just to prepend a url, set resolves/data, or run an onEnter/Exit function, then you'll additionally need to set template: "<ui-view/>".
See:
https://github.com/angular-ui/ui-router/wiki/Nested-States-and-Nested-Views#abstract-states
In my Angular app, I have the following sample route definition which uses nested views:
.state('mapping.project', {
authenticate: true,
url: '/:projectId/:projectName',
controller: 'ProjectCtrl as proj',
views: {
'': {
templateUrl: 'app/components/mapping/partials/project.html',
controller: 'ProjectCtrl as proj'
},
'details#project': {
templateUrl: 'app/components/mapping/partials/details.html'
},
'activityTypes#project': {
templateUrl: 'app/components/mapping/partials/activity-types.html'
},
'boundaryPartners#project': {
templateUrl: 'app/components/mapping/partials/boundary-partners.html'
},
'progressMarkers#project': {
templateUrl: 'app/components/mapping/partials/progress-markers.html'
},
'users#project': {
templateUrl: 'app/components/mapping/partials/users/users.html',
controller: 'projectUserCtrl as vm'
}
}
})
Each of these views is loaded within a tab, using Angular Material md-tabs: https://material.angularjs.org/latest/api/directive/mdTabs
The problem is, when I access the route mapping.project, the projectUserCtrl that you can see on my users#project view gets immediately called. I assume the same would be true for each individual controller that I have attached to my nested views.
I'd want to call these nested controllers only when the tab is active and that particular template loaded (in this case: users#project).
How do I do this?
You don't need all these child views, you only need 1, a container for the visible tab. Make separate states for each of the tabs, then route the child view accordingly when your "tabs" are clicked.
I'm not sure on the material design specifics, but in essence your tabs become just links ui-sref links.
For the past 9 hours I have been trying to implement a page with tabs using Angular and ui-router.
I have the following:
.state('someAbstractParentRoot', {
'abstract': true,
url: '/{id}',
templateUrl: '/admin/templates/rootTemplate',
controller: 'someController1',
data: {
breadcrumbLabel: 'Details'
}
})
.state(someAbstractParentRoot.child, {
url: '',
views: {
details: {
templateUrl: '/admin/templates/details',
controller: 'someController2'
},
videos: {
templateUrl: '/admin/templates/videos',
controller: 'someController3'
},
logs: {
templateUrl: '/admin/templates/logs',
controller: 'someController4',
},
notes: {
templateUrl: '/admin/templates/notes',
controller: 'someController5'
}
}
})
Using bootstrap I simply show the template I need.
so when the videos tab is shown, the url is something like: localhost:8080/users/1#videos.
So, this all works great until I need to send this link to someone, because when I do that, the details tab is automatically opened. I can't just toggle classes on div elements because some of the tabs are using ng-if so jquery doesn't pick up all of the html it should, probably because of angulars digest cycle (it can be solved with setTimeout, but I am trying to avoid that).
Does anyone know how I can use ui-router to define a tab which will support direct linking?
Some example would be very much appreciated.
NB: I need the abstract parent state.
Can urls in ui-router have a '#' symbol?
There is a problem with your states
actually you declare only one state which can be divided in several parts you have to declare a state for each subviews so declare something like. I don't know if you really need an abstract state so i can juste declare:
$stateProvider.state('details', {
templateUrl: '/admin/templates/details',
controller: 'someController2'
})
.state('videos', {
templateUrl: '/admin/templates/details.html',
controller: 'someController3'
})
.state('logs', {
templateUrl: '/admin/templates/logs.html',
controller: 'someController4'
})
.state('notes', {
templateUrl: '/admin/templates/notes.html',
controller: 'someController5'
});
In your rootTemplate juste add this
<div id="tabsContainer">
<a ui-sref="details">Details</a>
<a ui-sref="logs">Logs</a>
....
</div>
<div ui-view> </div> <!-- Where your state template will be inserted -->
I'm working on an angular app that has ui-router module.
When entering a certain state of the router, I show a modal dialog, which then replaces my parent view. I would like to keep the parent view and show the modal as overlay. Is there a way to do it with ui-router?
To give an example:
$stateProvider.state("clients.list", {
url: "/list",
templateUrl: "app/client/templates/client-list.tpl.html",
controller: moduleNamespace.clientListController,
resolve: {
clients: function (ClientService) {
return ClientService.all();
}
}
})
// This will replace "clients.list", and show the modal
// I want to just overlay the modal on top of "clients.list"
.state("clients.add", {
url: "/add",
onEnter: function ($stateParams, $rootScope, $state, ngDialog) {
ngDialog.open({
controller: moduleNamespace.clientAddController,
template: "app/client/templates/client-add.tpl.html"
});
$rootScope.$on("ngDialog.closed", function (e, $dialog)
if ($state.current.name !== "clients.list") $state.transitionTo("clients.list");
});
}
})
Thanks
I think the proper solution would be something like:
$stateProvider.state("clients.list", {
url: "/list",
templateUrl: "app/client/templates/client-list.tpl.html",
controller: moduleNamespace.clientListController,
resolve: {
clients: function (ClientService) {
return ClientService.all();
}
}
})
.state("clients.list.add", {
url: "^/add",
})
Important things are I made /add absolute by adding a ^. Most people would have just done /list/add because the default behavior of nested state is to add them together...the ^ bypasses this. You also would need to on state load style this thing so its a "modal" and is on top of other content.
And then inside of clients.list state you would need to update /client-list.tpl.html to have an ng-view that would style itself on top of the parent view.
I can create a plunkr if need be, but if I do that I am basically implementing everything for you.
Is it possible to setup a route in ui-router that only has a controller? The purpose being that at a certain URL, the only thing I'd like to do is take action programatically, and not display anything in terms of a view. I've read through the docs, but I'm not sure if they offer a way to do this.
Yes, I have read this: https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-open-a-dialogmodal-at-a-certain-state, but that is not quite what I am looking for.
For example, let's just say I have a basic body with view:
<body ui-view></body>
And some basic config:
// Routes
$stateProvider
.state('myaction', {
url: "/go/myaction",
onEnter: function() {
console.log('doing something');
}
});
When /go/myaction is visited, the view is blank. Is it possible to do this?
I was able to solve this problem by redirecting the headless state I was taking programmatic action in, to a state WITH a view at the end of the headless state:
$stateProvider
.state('myaction', {
url: "/go/myaction",
onEnter: function() {
console.log('doing something');
}
controller: function($state) {
$state.go('home');
}
});
You can't have a controller without a view but you can use onEnter instead of a controller. If you don't want to change the current view when accessing this state you can define it as a child state:
$stateProvider
// the parent state with a template
.state('home', {
url: '/home',
templateUrl: '/home.html',
controller: 'HomeCtrl'
})
// child of the 'home' state with no view
.state('home.action', {
url: '/action',
onEnter: function() {
alert('Hi');
},
});
Now in home.html you can do something like this:
<a href ui-sref=".action">Greet me!</a>
From the docs:
Warning: The controller will not be instantiated if template is not defined.
Why don't you use an empty string as a template to overcome this?
Yes, you can do that. Use absolute view names to re-use the <ui-view> of another state.
Take a look at this example:
Users go to my app, but depending on them being authenticated or not, I want to send them to a public or private page. I use the index state purely to see if they're logged in or not, and then redirect them to index.private or index.public.
The child states make use of absolute view names to use the <ui-view> element that corresponds to the index state. This way, I don't need to make a second nested <ui-view>.
$stateProvider.state('index', {
url: "/",
controller: 'IndexCtrl'
}).state('index.private', {
views: {
"#": {
templateUrl: 'private.html',
controller: 'PrivateCtrl'
}
}
}).state('index.public', {
views: {
"#": {
templateUrl: 'public.html',
controller: 'PublicCtrl'
}
}
});
A small note on this example: I'm using the # shortcut here. Normally you would use viewname#statename.
My solution for this was just to include a template (html file) that is blank.