baptistebriel / biggie

minimalist javascript frontend framework w/ bigwheel

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Reusable component

vblazenka opened this issue · comments

Hi, love the job you did with biggie!

I come from the React world, and I'm thinking in terms of reusable components.

I would like to create persistent navigation that will be always on top, and I want to create js file for handling navigation animation.

Where can I put that navigation, and where should I init that navigation javascript so that it will be always included?

I'm just thinking in a reusable way so that I don't have to copy-paste my markup on all views, and always to the same animation in every view.

I looked at this issue: Persistent Navigation #177

Hey @wedranb,

You should take another look at the solutions for issue #177, because I originally opened that issue with the exact same questions you're having. One thing to keep in mind is that in those solutions, you will see the method dataAdded referenced. Since then, this method has been renamed ready.

If you still can't get it working based on those solutions in #177, let me know!

Let's say I put markup outside main. How can I create js file for managing my navigation animations and where to init that code?

And what if I don't need navigation, but let's say I have some kind of navigation for sliding images somewhere. But that navigation has complex animations and I want it to be a part of the Home section.

I would have Home.js and ImageSlider.js. And I would like to init my ImageSlider when Home is initialized. I tried looking at bigwheel docs and require my ImageSlider with Home, but home view would just be added to the DOM 2 times.

I tried to require my slider as a section. :/
[ require('./sections/Home'), require('./sections/ImageSlider') ]

What you were trying to achieve is multi section routes. There is indeed this feature in bigwheel, but it's not really implemented/used in biggie. It would be interesting to see how it be implemented to work as #177.

For all markup outside of <main>, I would attach any dom events / animations in assets/js/app.js so it's just called once and never destroyed. I usually do this when creating a menu.

If you'd like to have some kind of components inside a section, i.e. a slider inside of Home.js, I'd create another class that would be initialised/destroyed inside of section Home.

js/components/slider.js

class Slider {

  constructor(opt) {

    this.init()
  }

  init() {}

  destroy() {}
}

module.exports = Slider

js/sections/home.js

import Default from './default'
import Slider from '../components/slider'

class Home extends Default {

  constructor(opt) {

    super(opt)

    this.slug = 'home'
    this.components = []
  }

  init(req, done) {

    super.init(req, done)
  }

  ready(done) {

    super.ready()

    this.addComponents()
    done()
  }

  addComponents() {
    
    const options = {}
    const slider = new Slider(options)
    
    this.components.push(slider)
  }

  removeComponents() {

    this.components.forEach((component) => {
      component.destroy()
    })
  }

  destroy(req, done) {

    super.destroy()

    this.removeComponents()

    this.page.parentNode.removeChild(this.page)

    done()
  }
}

module.exports = Home

What do you think about this approach?

Maybe we could have an array of imports that corresponds to components (in the constructor of Home.js) that would automatically gets called / destroyed in the parent class Default.js?

js/sections/default.js

class Default {

  constructor(opt = {}) {
          
    // ...
    this.components = null
  }

  ready() {

    // ...
    this.components != null && this.addComponents()
  }

  addComponents() {
    
    this.components.forEach((component) => {
      const instance = new component()
      // now do something with instance...
    })
  }

  removeComponents() {

    this.components.forEach((component) => {
      component.destroy()
    })
  }
}

js/sections/home.js

import Default from './default'
import Slider from '../components/slider'
import AnotherOne from '../components/anotherone'

class Home extends Default {

  constructor(opt) {

    super(opt)

    this.slug = 'home'
    this.components = [Slider, AnotherOne]
  }
}

module.exports = Home

This code isn't tested yet, but we could make something like this work! As soon as you don't have 20 components inside a page, you can go with the first example. ;)

This approach would let us create a base class for components.
Let me know what you think!

@baptistebriel I didn't have much time this week to try and implement your suggestions. I will try to jump on it tomorrow and get back with the results. Cheers! :)

I will close this issue since I found a solution. I went with approach of initializing/destroying component inside of a home section.

But I would suggest to open a new issue (feature request) for creating this better for biggie. We can discuss it there.

Cheers! :)