Attempting to make a Navigation Component

So, I’m trying to abstract my application out into components, but I’m not really sure what I’m doing.

I’m guessing on a lot of what I’ve done, and I don’t really know how to go forward.

I have created a “bootstrap-navbar” component with JS:

with STACHE:

An “app-navigation” component with JS:

with STACHE (utilizing <bootstrap-navbar>):

Then used <app-navigation/> in index.stache.

I know there has to be something wrong with this approach; it just doesn’t feel right.

Any insight as to how to do this properly would be appreciated. For example, how should I manage a list of pages, and How should I pass the active state down to the component that is rendering the navigation?

Reasons why I might question my current approach:

  • First time using {{#each}} and route.
  • First time trying to add custom [pages] data to ViewModel.
  • Don’t know how to pass down “active” state to bootstrap-navbar component without making it dependent.
  • The bootstrap-navbar STACHE expects to receive {{pages}}, which is defined on the app-navigation ViewModel; not sure about the sanity/portability of this API.
  • Not sure about use of Map vs. DefineMap for the ViewModel (have seen some Map examples where only certain data is inside the define, while the rest is not, but not sure why/what that means).
  • What if I wanted to be able to toggle some functionality within bootstrap-navbar, like the collapse functionality? How would I specify that when using the component?

Feels “kludge-y”. What’s a better way of doing this?

If I were creating this as a custom element in Polymer, I think the API would look more like:

<bootstrap-navbar collapse="true">
  <a href="/">Home</a>
  <a href="photo" class="active">Photos</a>
  <a href="video">Videos</a>
</bootstrap-navbar>

Which would be closer to “platform” but not sure how to accomplish this style of custom element or if it makes sense to do it this way in Done/CanJS. It’s just easier to reason about, and what I’m more familiar with. I do imagine I could have the {{#each}} in the mustache template spit out the <a/>s, but I could also probably just do it the way I’m already doing it. Obviously, I’m a bit confused; I hope someone can clear this up for me.

The following multi-select component has given me a lot of insight how I should build my component:

So, it looks like I should be able to keep the bootstrap-navbar component just expecting elements like I outlined in my last reply. In the multi-select component, they also specified an API to pass list="" and selected-prop="" attributes (instead of HTML elements) which is cool:

But I’ll probably just stick with the element method, to keep things simple.

1 Like

interesting approach. how does your nav-component now look like?

I’ve extracted the Bootstrap stuff out into a DoneJS plugin separate from my main project:

I actually decided to try and implement the attribute method because I realized that would actually be easier (no having to parse inner DOM and watch for mutations with observers) but I am stuck trying to implement the component demo if you would take a look:

The comment shows what I was trying before resorting to creating a “dummy-element” which does seem to work. Mind you I am using the bleeding edge packages (see package.json) and am not entirely sure how to setup the view model like I was trying to do in the commented area if you or anyone else has any insight on that would be great!

Solution found for adding to the #demo element’s viewModel:

Needed to use document.getElementById("demo") instead of $("#demo").