Only change one viewport in Aurelia router - aurelia

Good morning, I have my route setup as shown below within Aurelia CLI.
config.map([
{
route: [''],
viewPorts: {
'side': { moduleId: 'side' },
'main': { moduleId: 'main' }
},
title: 'Test',
nav: false,
name: 'Temp'
]);
What I would like to do is based on what I select on my side view, I just want to change the moduleId for main and load that view.

I don't think there's a way to dynamically change the moduleId of a view-port. I see 2 options to solve your proble:
1 - Create another route, changing the moduleId of one of the viewports
2 - Use the layout mechanism and change its content in run time. I recommend you to read http://aurelia.io/hub.html#/doc/article/aurelia/router/latest/router-configuration/10.
I know this is not the answer you were expecting but I hope it helps.

Related

How to dynamically build navigation menu from routes linking to parent/child views/controllers

This question is a follow-up question for my original question Linking directly to both parent+child views/controllers from the main navigation menu
The accepted answer is great, but later when I added a 2nd "childRoute" dynamically, I noticed a problem. In order to build my navigation dynamically I had to add the multiple routes with the same "route" attribute. (see app.js in the example code below). The only difference were the "title" and "settings" attributes.
configureRouter(config, router){
config.title = 'Aurelia';
config.map([
{ route: 'shared-parent', moduleId: './shared-parent', settings: { childRoute: 'child-a' }, nav: true, title: 'Shared Parent - child-a' },
{ route: 'shared-parent', moduleId: './shared-parent', settings: { childRoute: 'child-b' }, nav: true, title: 'Shared Parent - child-b' },
...
]);
this.router = router;
}
The settings attribute I used in the view for doing this:
<a if.bind="row.settings.childRoute" href.bind="row.href + '/' + row.settings.childRoute">${row.title}</a>
I know it's not pretty but it does navigate to the right child route. The problem is that it's always the last of the 2 routes with duplicate "route" attributes that is marked as active.
The reason why I added the settings: {childRoute: 'child-a/b' } instead of giving them distinct "route" attributes like route: 'shared-parent/child-a' and route: 'shared-parent/child-b' was that the url would actually then match shared-parent/child-a/child-a and shared-parent/child-b/child-b since we're first linking to the shared-parent.
This live runnable gist should clearly display the problem (child-a route never activating): https://gist.run/?id=95469a9cb3a762d79da31e0b64248036
Ps.
If you have a better idea of what to call the title of this question please feel free to edit it.
So I took a stab at your problem using the EventAggregator in the Activate lifecycle hook in the child view models.
https://gist.run/?id=bfb5df5e39ac0bb73e9e1cae2d2496e2
in the child view models, I just published an event stating the child route was updated:
activate(params, routeConfig, navigationInstruction) {
let payload = navigationInstruction.parentInstruction.config.title;
payload = payload.substring(0, payload.length - 7);
this.aggregator.publish("child route updated", payload + "child-a");
}
In the app.js file, I updated the route titles, and added an activeChild property. Next, update the activeChild property when the event is captured:
constructor(aggregator) {
this.aggregator = aggregator;
this.aggregator.subscribe("child route updated", payload => {
this.activeChildRoute = payload;
console.log(this.activeChildRoute);
});
}
Finally, I updated the class expression on you list item to update based on that active child Flag:
<li repeat.for="row of router.navigation"
class="${row.title === activeChildRoute ? 'active' : ''}">

Aurelia nested routers and router-views

I want to have a list of courses on the screen(contrived example). When you click a course, it expands(still showing the list of courses) into a list of students that take the course. When I click a student it must expand into a view of the students details(still showing the list of students AND the list of courses). etc.
So basically I want to have nested routers, I think?
Example, app.js
config.map([
{route: "", moduleId: 'no-selection', title: 'Select'},
{route: "course/:course-id", moduleId: 'course', name: 'course'}
]);
course.js(inject the router):
this.router.configure(config => {
config.map([
{route: "course/:course-id/student/:student-id", name: "student", moduleId: "student"}
]);
})
student.html has its own router-view element
The above works, BUT when i click a top level link(a course), the content gets put in the inner router-view. Even worse, there is now a router-view in every student that gets expanded, how do I manage this?
Basically I can't find any documentation on how to do this - the child router stuff doesn't seem to be exactly what I need? Any help will be appreciated.
Let's look at this and how we can implement this with a single router. Here is the route structure I might use.
[
{ route: "", moduleId: 'no-selection', title: 'Select'},
{ route: "course/:courseId/:studentId?", moduleId: 'course', name: 'course'}
]);
The studentId parameter is optional.
Then I would look at how to use this course page to do everything you want based solely on the parameters it receives in the activate callback.
I don't have time to give a full answer right now, but hopefully this will help lead you down the right path!

Scroll event doesn't trigger

I have a problem with scroll binding. I tried to use scroll binding and event listeners without luck. Using jquery doesn't work either. Any other event I tried works as expected, but with scroll it does literally nothing. No error, no message .. What am I missing?
Edit
Ok I made a mistake and didn't put it in the app.js and app.html as mentioned in examples but one layer under so there was no scroll event to catch on the element. If I put scroll.trigger there it works.
New question:
Can scroll be triggered in children views?
Eg.: lets say you have 2 view-models on 2 routes and you want one to trigger scroll event and the other not to. Can someone point me to right direction?
Can check this ? website for detail
I found mistake causing my original problem - it is described in question.
To answer my second question I used this solution:
app.html
<div class="page-host" scroll.trigger="handleScrollEvent($event) & debounce:200">
<router-view></router-view>
</div>
app.js
export class App {
configureRouter(config, router) {
config.title = 'Title';
config.map([
{ route: ['', 'first'], name: 'first', moduleId: './first', nav: true, title: 'First route' },
{ route: ['second'], name: 'second', moduleId: './second', nav: true, title: 'Second route' }
]);
this.router = router;
}
handleScrollEvent(e) {
// if not on specified route
if(this.router.currentInstruction.config.name !== 'second') {
return;
}
// if scrolled under defined pixels
if(e.target.scrollTop > 100) {
$('body').find('#toolbar').addClass('fixed');
} else {
$('body').find('#toolbar').removeClass('fixed');
}
}
}
I don't know how clean it is but it is working. Feel free to sugest other solution.

How can I show/hide navigation elements based on a user's state using Aurelia

I am quite new to Aurelia and I am loving every minute of the leaning curve. I am using Aurelia's Skeleton Navigation for es6 apps and I am currently working on a simple app where a user logs in and submits a story after providing certain details. The flow of my app is fairly simple:
Login Screen --> Screen where user provides phone number --> User submit's story
My navigation bar has "Home" and "Submit Story". However, I want to hide the "Submit Story" menu item until after the user has provided his phone number. So basically on phone number submit, if the function returns true I need the menu item to show up.
I think there are two ways to go about this. One is by binding the nav items to a true or false value depending on whether the phone number is submitted, and the other is to dynamically add the route on a successful submission of the phone number. Which one is better to use? And I would greatly appreciate a nudge in the right direction.
I tried assigning a boolean variable to the routes but it gave me mixed results. See the code below (I have included just the related code):
check_phone = false;
configureRouter(config, router) {
config.title = 'Aurelia';
config.map([
{route: ['', 'home'], name: 'home', moduleId: 'home', nav: check_phone, title: 'Home'},
{route: 'story', name: 'story', moduleId: 'story', nav: check_phone, title: 'Submit a Story'}
]);
config.mapUnknownRoutes('/');
this.router = router;
}
phone_submit() {
if(success) this.check_phone = true;
}
I also tried dynamically adding the route but it does not work:
configureRouter(config, router) {
config.title = 'Aurelia';
config.map([
{route: ['', 'home'], name: 'home', moduleId: 'home', nav: check_phone, title: 'Home'},
]);
config.mapUnknownRoutes('/');
this.router = router;
}
phone_submit() {
if(success)
this.router.addRoute({route: 'story', name: 'story', moduleId: 'story', nav: true, title: 'Submit a Story'})
this.router.refreshNavigation();
}
Please assist me in this. Thank you for your time!
There is actually a settings property on the route. You can set the settings property to an object in which you can manipulate. You can use this object when you render your route and have the nav bar hide it if it has a particular property.
e.g.
{route: user/:id',
name: user,
moduleId: './Aurelia/users,
nav: false,
title: 'User',
settings: {isShown: true}
}
Check my article on linked-in on the topic which explains using the settings property more thoroughly;
https://www.linkedin.com/pulse/routing-aurelia-framework-mike-gold?trk=mp-author-card

Route and subroute based on user in hottowel asp.net mvc4

:updated
can anyone help me found out how to create routes and subroute based on user
is it possible to create a Widget that will do the job if so how
this is how my menu looks like (note:all menu items together let us call it master):
-Home
-shop
-men
-women
-food
-dog
-human
-cart
-settings
-user
-images
-themes
let say i have the following userGroup:
-Admin
-visitors
-vip
-costumers
-co-workers
what i want to do ist some thing like
if(user == Admin){
destroy the current menu then make a copy of master **master** remove subroute women and subroute dog then push
}else if(user == visitor){
...
}
or is there a better way to do this and where i am supose to define it?
First you might want to consider upgrading your project to Durandal 2.0 since it removes the dependency on sammy.js in favor of a custom router which works much better (Durandal 1.0 is essentially obsolete now). Here is the page on upgrading: http://durandaljs.com/documentation/Conversion-Guide/
and here are the docs on the new router: http://durandaljs.com/documentation/Using-The-Router/
As for handling the routing based on user, since router.map just expects an array of routes you can just build up the array conditionally and pass it to router.map
var routes = [ { route: '', moduleId: 'hello/index', title: 'Hello World', nav: true },
{ route: 'men', moduleId: 'men/index', title: 'Men', nav: true }]
if(user == Admin){
routes.push({ route: 'admin', moduleId: 'admin/index', title: 'Admin', nav: true }
}else if(user == visitor){
routes.push({ route: 'women', moduleId: 'women/index', title: 'women', nav: true }
}
return router.map(routes)
.buildNavigationModel()
.mapUnknownRoutes('hello/index', 'not-found')
.activate();