Dynamic NavMenu Width

Attempting to modify the NavMenu width whilst hiding text using CSS from the standard VM having trouble getting it to work. In due course want to add a toggle button so user can change this. I started using this reference (https://ilikekillnerds.com/2016/02/binding-with-style-in-aurelia/)

Adding style=“width: 25%” or css.bind ="{width: ‘25%’}" to a <div> in the html works OK.
However, adding css.bind="_width" where _width is defined in the .ts file does not work. The icon is correctly shown but the width remains unchanged. The constructor never appears to fire using the breakpoint in debug mode. Even setting it in declaration without having a constructor does not work. The string may be wrong but already tried all variations I can think off (eg “width: ‘25%’”, “width=‘25%’” etc). Also tried value.bind, style.bind which do not work either. Is this not possible?

image

image

From the commented html, this is my guess:

<div css="width: ${_width}%;"></div>

Note: then you only need to set width to a number, not a string. This is easier to work with, and clearer think about in data driven way.

Thanks for help. I have tried this but still cannot get it to work. For some reason, I do not understand, the out of the box (OOBE) navmenu component does not seem able to process the navmenu.ts file. Neither can the full blown project. I created a navmenu.ts file in the correct location but unable to get Aurelia to bind to it. The implicit binding uses the router in the top level view model app.html. Any idea how to move this forward? I need to add a toggle button that enable user to collapse the navmenu to icons and expands the other view port to increase usable screen estate.

image

You are pulling in nav menu as navmenu.html, which means your view model is not used at all. change it to: <require from="../navmenu/navmenu"></require>

I did try this but seems to work the other way round to expected. Not sure what is wrong. The application then has no navmenu as shown below. Is there anything else to check? Could it be anything to do with Microsoft changing versions of TypeScript in Visual Studio 2017? No error messages appear in the console.

image

If I change it back to include.html in the <require> it looks fine.

Your view model will result in nav-menu custom element name, while the file name of the view results in navmenu. You can either change the template or the name

Thanks. I have changed view model name (including filenames) and <require> to <require from="…/navmenu/nav-menu"> and confirm the breakpoints are being reached in Visual Studio. Now it doesn’t startup (Error: Cannot read property?) so wondering how to correct this.

You have a @bindable on top of your class, remove it and it should work fine

Thanks. Application starts up but cannot see any routes. I presume as before the router still works when bound to the html in nav-menu. I’ve single stepped through app.ts and the routes are being produced. Anything missed out? A compose view?

image

You don’t have @bindable router in your view model. That’s the different between the view and the view model.

Thanks. I’ve added this in now. This now works. I read most of the Aurelia books but none described what needed to be done in this case :slight_smile:

I noticed the activate() method never fires. Is there a way of using Aurelia via view/view models without using jQuery to change the widths (eg the css class=“col-sm-7”) of the viewports defined in app.html since would like to close in the white space?



image

It’s a normal custom element, activate should not fire. For a normal custom element, you are guaranteed to have all necessary value during .bind() lifecycle. Whatever you want to do in activate, you can do it in .bind(). Remember to call somePropertyChanged() if you want to trigger change handler, as they won’t be fire for the initial value if you hook into .bind().

Change

@bindable({ defaultBindingMode: bindingMode.twoWay }) router: Router;

to

@bindable() router: Router;

As you don’t need it to be two way.

For the white space, you can use html-minifer in html-loader to minimize all the space, or if you are to solve it differently, you can put the opening div of next column next to closing div of previous one. Or you can use flex, or some other… it depends

The finished view model and html template are now working as follows.

nav-menu.ts

nav-menu.html

app.html

There is always room for improvement. The navigation does not gracefully degrade and the hamburger button not visible at normal sizes. The white space could be reduced by using a 16/24 column customised bootstrap for example

Glad to see it working. For those element reference with ID, you can leverage aurelia ref feature to get a hold of the element during bind() or attached()