Adding or not adding route in Aurelia - aurelia

I am trying to add a route deppending on a boolean, so if the condtion is meet the route will show and be in the navbar and if not it will not be added.
I have trided to change nav: option depending on a condtion, but I have missed something...
{
route: 'aRoute',
moduleId: 'modules/something/mySite,
nav: cond ? true : false,
title: 'mySite',
isStatic: false
}
Probably I am stupid but I need help on this.. :/

I'm not 100% sure, but routes are probably built one time and reused, at least those that are part of navigation model (nav === true). That would mean that you cannot use dynamic expression for nav as it would be processed only once.
If you only need this for the purpose of displaying the route in navbar, then you can create a workaround using settings property to mark the route somehow and do condition check when creating navbar.
{
route: 'aRoute',
moduleId: 'modules/something/mySite,
nav: true,
title: 'mySite',
settings: { occasionallyVisible: true } // add your own properties here...
}
I used settings.occasionallyVisible property, but you can add whatever you like.
<li repeat.for="route of router.navigation"
if.bind="!route.settings || !route.settings.occasionallyVisible || cond">
<a href.bind="route.href">${route.title}</a>
</li>
Navigation route will be displayed if it doesn't have settings property OR settings.occasionallyVisible is falsy OR cond is true. Of course, cond would be that condition you need.
Not as elegant, but it should get the work done until you get the better answer :)

The following post should help you do what you want:
http://odetocode.com/blogs/scott/archive/2016/05/31/dynamically-add-routes-in-aurelia.aspx
It shows how to add a route dynamically by doing this:
this.router.addRoute(
{ route: "secret", name: 'secret', moduleId: "app/secret",
title:"Secret", nav:true
}
);
then refreshing the router with this method call (which you are apparently missing):
this.router.refreshNavigation();

Related

Vuetify v-treeview doesn't delete node

I am a beginner in vuejs and vuetify and I try to add and remove nodes in a treeview.
When I do a .push(item) the treeview updates but when I delete an item from my array, the treeview does not update.
Here is an example of my code
My treeview
<v-treeview
[...]
:items="formatedItems"
item-key="slug"
[...]
>
[...]
</v-treeview>
formatedItems is declared in the data like this :
data: () => ({
[...]
formatedItems: [{
id: 0,
slug: null,
name: i18n.t(****),
children: []
}]
[...]
}),
This code correctly adds a child in my treeview :
this.formatedItems[0].children.push({
id: element.id,
slug: element.slug,
name: element.name,
children: []
});
On the other hand, this code removes the item from my array but doesn't update the treeviews :
_.remove(this.formatedItems[0].children, function(n) {
return n.slug == element.slug;
});
this.formatedItems = this.formatedItems; // I tried this to trigger a potential magical update of vuejs but nothing...
I don't know what to try anymore, that's why I come to ask you the question:
.push being a build-in function and knowing that I use a lodash function for deletion, is there something I didn't understand about the use of vuejs that causes my treeview not to be updated?
Thank you for your attention
Looks like the problem somewhere else. I've tried a basic example and all works fine.
Except I used filter method for deletion.
codepen.io/DavidGolodetsky/pen/eYZMbgm

Dynamic parameter in href option in Aurelia Routing config.map

This seems like a really simple issue, but it's driving me crazy...
Does anyone know how I can specify a dynamic :id parameter in the href routing configuration option?
The following unfortunately doesn't work:
config.map([
// ... default parameterless routing here
{
route:[':id/request'],
moduleId:'processes/bdd/request/request',
name:'Request', title:'Request', href:`#/bdd/request/${id}/request`, settings:{type:'Request', icon:''}, nav:true,
},
{
route:[':id/requestAuth'],
moduleId:'processes/bdd/request/requestauthorization',
name:'RequestAuthorization', title:'Request Authorization', href:`#/bdd/request/${id}/requestAuth`, settings:{type:'Request', icon:''}, nav:true,
},
// ... some additional mappings here
]);
The href property is static. If you want to generate a route for a link using this route, you could use the route-href custom attribute like this:
route-href="route: request; params.bind: { id: someProp }"
Note that I changed the route name to be camelCase (all lowercase since it is one word here) to match the route naming convention.
I had a similar use case and I was able to get this to work by adding a pipeline step to the router that alters the config on the fly.
My use case may be a little different in that I only want the item to appear in the nav bar when the route is active -- say I have routes /abc, /def/:id, and /ghi -- when the active route is ABC or GHI, only those items will appear in the nav bar, but when the active route is DEF, it should appear in the nav bar, and clicking it should lead to the same DEF ID you're currently looking at. So my route configuration includes a setting that indicates the route should only appear in the nav bar when it's the active route.
Here are the interesting parts of my actual configureRouter function:
configureRouter(config, router) {
config.addPreActivateStep(Preactivate); // explained below
config.map([
// some routes
{ route: 'patients/:patientId', name: 'patient-master',
moduleId: 'patients-and-cases/patient-master/patient-master',
title: 'Patient', nav: true, settings: { renderOnlyWhenActive: true },
href: '#' // it doesn't matter what this is
},
// more routes
]);
}
And here is the Preactivate class that sets the href on preactivate:
class Preactivate {
run(routingContext, next) {
routingContext.config.href = routingContext.fragment;
return next();
}
}
If, unlike me, you want this to display in a nav bar all the time, this will still work -- the href will simply remain set to the last thing it was set to when the route was active. In that case you'd probably want to initialize it to some default value that makes sense.

Dynamically Adding / Removing Route in Durandal Router when application is loaded

I need help in dynamically adding/removing route in Durandal Router. What I want is after user is logged in then I would be able to add or remove specific route depending upon logged in user's type.
I tried to add/remove route from visibleRoutes/allRoutes array ... but get binding exception from knockout library...
I was hoping it would be common scenario... but still couldn't find any solution ... please help me in fixing this issue.
Thanks.
Wasim
POST COMMENTS:
I tried this function to dynamically hide/show route... and similary tried to add/remove route from allRoutes[] ... but then get exception on knockout bidning
showHideRoute: function (url,show) {
var routeFounded = false;
var theRoute = null;
$(allRoutes()).each(function (route) {
if (url === this.url) {
routeFounded = true;
var rt = this;
theRoute = rt;
return false;
}
});
if (routeFounded)
{
if (show)
{
visibleRoutes.push(theRoute);
}
else
{
visibleRoutes.remove(theRoute);
}
}
}
In Durandal 2.0.
You can enumerate the routes to find the one you wish to show/hide.
Then change the value of: nav property
Then run buildNavigationModel();
here is an example:
// see if we need to show/hide 'flickr' in the routes
for (var index in router.routes) {
var route = router.routes[index];
if (route.route == 'flickr') {
if (vm.UserDetail().ShowFlickr) { // got from ajax call
// show the route
route.nav = true; // or 1 or 2 or 3 or 4; to have it at a specific order
} else if (route.nav != false) {
route.nav = false;
}
router.buildNavigationModel();
break;
}
}
Durandal 2.0 no longer has the method visibleRoutes. I found that the following works for me.
router.reset();
router.map([
{ route: 'home', moduleId: 'home/index', title: 'Welcome', nav: true },
{ route: 'flickr', moduleId: 'flickr/index', title: '', nav: true }
])
.buildNavigationModel()
.mapUnknownRoutes('home/index', 'not-found');
This removes all previous routes, if you want to maintain current routes you could try using the router.routes property to rebuild the array of routes.
I had a similar requirement. If I were you, I would take another approach. Rather than adding/removing routes when application loads - get the right routes to begin with per user type.
Two options, (I use both)
1) have a json service provide the proper routes per user type, this approach would be good if you need to 'protect/obscure' routes... i.e. I don't want the route referenced on any client resource.
2) A simpler solution see Durandal.js: change navigation options per area
You can have a settings property identify the user type.
I hope this helps.
I had a similar problem: First, router.visibleRoutes() is an observable array. In other words, when you change its value, the routes automatically update. However, the items in this array are not observable, so to make a change you need to replace the entire array and not just make a change to a single item in it.
So, all you have to do is find which item in this array you want to remove, and then create a new array without this item, and set router.visibleRoutes() to this new array.
If, for example, you find out the it is the 3rd item, then one way of doing it is:
router.visibleRoutes(router.visibleRoutes().splice(2, 1))
Note that splice() returns a new array where an item is removed. This new array is put into router.visibleRoutes.

Load html data with AJAX in Sencha touch when panel is shown

I have a TabPanel with a Tabbar and four panels inside. I want to load the HTML content for the fourth panel with an AJAX call when the panel becomes visible.
The AJAX function fetches the data from the server and places it inside the panel, which uses the panel update function. The problem is how to call this function when the panel becomes visible. A simplified version is:
Pages.Contact = new Ext.Panel({
title: 'Contact',
html: 'test data',
iconCls: 'user',
cls: 'cHome',
activate: function () {
Pages.Contact.update("my ajax data");
}
});
When I go to my panel the body content is not affected. Does anyone know what goes wrong here? I've already tried to replace activate with render and show.
To add event's listeners you need to do
listeners: {
activate: function(){
console.log('activate fired');
}
},
But that's not the event you want to listen. It's better to listen for beforecardswitch on the TapPanel object, example:
listeners: {
beforecardswitch:function(newCard, oldCard, index, anim){
if(index == 3){
//loadJson and update card.
// you may want to use this also
newCard.setLoading(true);
//and after the json request has finished set it to false.
}
}
},
The solution was to use:
beforecardswitch:function(object, newCard, oldCard, index, anim) {
As shown by Ilya139 by with the object parameter as first parameter.
Then the index variable returns the correct cardnumber.

Using dijit.InlineEditBox with dijit.form.Select

I'm trying to use a dijit.form.Select as the editor for my dijit.InlineEditBox. Two problems / unexpected behavior seem to occur:
Inconsistently, the InLineEditBox doesn't have the initial value set as selected
Consistently, after selecting a choice, the value that should be hidden is shown instead of the label.
The width isn't set to 130px
Here's working code: http://jsfiddle.net/mimercha/Vuet8/7/
The jist
<span dojoType="dijit.InlineEditBox" editor="dijit.form.Select"
editorParams="{
options: [
{label:'None',value:'none'},
{label:'Student',value:'stu'},
{label:'Professor',value:'prof',selected:true},
],
style:'width:1000px;',
}"
editorStyle="width: 1000px;"
>
</span>
Any help is greatly appreciated! Thanks!
Okay, after a few MORE hours struggling with the mess that is dijit.InlineEditBox, I think I have the solution to the remaining issue (#2).
EDIT: My first solution to #2 is still flawed; the implementation at http://jsfiddle.net/kfranqueiro/Vuet8/10/ will never return the actual internal value when get('value') is called.
EDIT #2: I've revamped the solution so that value still retains the real (hidden) value, keeping displayedValue separate. See if this works better:
http://jsfiddle.net/kfranqueiro/Vuet8/13/
First, to recap for those who weren't on IRC:
Issue #1 was happening due to value not being properly set as a top-level property of the InlineEditBox itself; it didn't pick it up properly from the wrapped widget.
Issue #3 was happening due to some pretty crazy logic that InlineEditBox executes to try to resolve styles. Turns out though that InlineEditBox makes setting width particularly easy by also exposing it as a top-level numeric attribute. (Though IINM you can also specify a percentage as a string e.g. "50%")
Now, issue #2...that was the killer. The problem is, while InlineEditBox seems to have some logic to account for widgets that have a displayedValue attribute, that logic is sometimes wrong (it expects a displayedValue property to actually exist on the widget, which isn't necessarily the case), and other times missing entirely (when the InlineEditBox initializes). I've worked around those as best I could in my own dojo.declared extensions to InlineEditBox and the internal widget it uses, _InlineEditor - since generally it's a good idea to leave the original distribution untouched.
It's not pretty (neither is the underlying code I dug through to understand and come up with this), but it seems to be doing its job.
But man, this was rather interesting. And potentially pertinent to my interests as well, as we have used this widget in our UIs as well, and will be using it more in the future.
Let me know if anything backfires.
hm...
<span dojoType="dijit.InlineEditBox" editor="dijit.form.Select"
editorParams="{
options: [
{label:'None',value:'none'},
{label:'Student',value:'stu'},
{label:'Professor',value:'prof',selected:true},**<<<<** and this comma is for?
],
style:'width:1000px;',**<<<<** and this comma is for?
}"
editorStyle="width: 1000px;"
>
</span>
Also, when using dijit.form.Select, selected value is not attr "selected" but value.
And if you enter prof inside <span ...blah > prof </span> than your proper selected option will be selected ;)
Dijit select checks for VALUE, not attr.
This may be fixed in recent Dojo - see http://bugs.dojotoolkit.org/ticket/15141 - but using 1.7.3 I found this worked:
In my app directory, at the same level as dojo, dijit and dojox, I created a file InlineSelectBox.js which extends InlineEditBox with code to set the HTML on the associated domNode from the value of the Dijit, and which wires up that code to the onChange() event:
define(["dijit/InlineEditBox",
"dijit/form/Select",
"dojo/on",
"dojo/_base/declare",
"dojo/_base/array"
],
function(InlineEditBox, Select, on, declare, array){
return declare(InlineEditBox, {
_setLabel: function() {
array.some(this.editorParams.options, function(option, i){
if (option.value == this.value) {
this.domNode.innerHTML = option.label;
return true;
}
return false;
}, this);
},
postMixInProperties: function(){
this.inherited(arguments);
this.connect(this, "onChange", "_setLabel");
},
postCreate: function(){
this.inherited(arguments);
this._setLabel();
}
});
});
Then, in my view script:
require(["dojo/ready",
"app/InlineSelectBox",
"dijit/form/Select"
],
function(ready, InlineSelectBox, Select){
ready(function(){
// Add code to set the options array
var options = [];
// Add code to set the initial value
var initialValue = '';
var inlineSelect = new InlineSelectBox({
editor: Select,
editorParams: {options: options},
autoSave: true,
value: initialValue
}, "domNodeToAttachTo");
});
});
I was dealing with this situation a few months ago, and not finding a resolution i made my own algorithm.
I put a div with an event on Onclick that build programatically a Filtering Select on that div with the store i want to use.
function create(id,value){
var name = dojo.byId(id).innerHTML;
dojo.byId(id).parentNode.innerHTML = '<div id="select"></div>';
new dijit.form.FilteringSelect({
store: store,
autoComplete: true,
invalidMessage:"Invalid Selection",
style: "width: 80px;",
onBlur: function(){ },
onChange: function(){ },
required: true,
value: value,
disabled: false,
searchAttr: "name",
id: "status"+id,
name: "status"
},"select");
dijit.byId('status'+id).focus();
}
I used the onBlur event to destroy the widget and the onchange to save by xhr the new value.
The focus is below because the onBlur was not working properly.
note: the function is not complete.