Giter VIP home page Giter VIP logo

Comments (3)

crabmusket avatar crabmusket commented on June 16, 2024

You can definitely do that. I advocate separating render functions completely into their own files because

  1. Hot reloading is easier to do
  2. It makes it more difficult for the view to update model state in unexpected ways (the only sanctioned way is by binding channels to the DOM) There is always the possibility for local state in renderers, what you want is for the model to control access to itself via channels
  3. Ideologically, model and view should be separate. There are many ways one might want to render a boolean state; so instead of duplicating the state in several components (tickbox component, switch component), separate state and renderer (boolean state + tickbox renderer or switch renderer)

2 and 3 are just my opinion. Raynos does seem to lean more componentwards in some of the examples, for example how most render methods are attached to an object, not completely free.

from mercury.

criloz avatar criloz commented on June 16, 2024

@shoover is not a requirement of the library just a way in which Raynos do the examples, because he likes more functional programming, in your case I see that you want to use and OO paradigm, a option then is create local state in each component, and attach them to his parent component state, and the state of the parent to the parent-parent state, and soon on till the root State (making you State tree in the process) when the class are loaded, using observ-struct, observ-array, or observ-varhash. if you are careful and understand the code that is really small and easy to comprehend, you will archive the same using the OO paradigm.

this approximation is good for me because In my case when I think about the model of the app, I relate it more with the db data (users, tasks, messages, etc.) very similar to what I should have in my db. the ui for me can represent that data in different ways, so the state of db like data should not be tied to a UI component. and the Ui component should has its own state. (is just my way of thinking)

I archive those things in this way (Warning: this is pseudo code can contains many errors)

// Create global variable that you will use  ref the db models
GLOBAL_VARIABLE = {};

// load your model here, you can define all your model structure like
// you do when use db-schemes using for example an observ-struct (I prefer this way),
// or in scheme-less approximation  using observ-varhash  
// and reference to the db model in the global variable

GLOBAL_VARIABLE.model = mercury.varhash({});

// load the ui root component, you should create the UI state tree in the process
var ui = new UI()

// Create the app state
var appState = mercury.struct({
    "model": GLOBAL_VARIABLE.model,
    "ui": ui.state
});

//start mercury
mercury.app(document.body, appState, ui.render);

// Ui class implementation 
class UI {
    constructor() {
        // we create ui root state
        let state = {
            show: mercury.value("c1");
        }

        // load your component 1
        this.c1 = new Component1();
        state["c1"] = c1.state
            .
            .
            .
            .
            // load your component n
        this.cn = new Component_n();
        state["cn"] = cn.state

        // the magic occurs here 
        this.state = mercury.struct(state);

        // subscribe to child events
        this.c1.onClose(this.closeView);
        .
        .
        .
        this.cn.onClose(this.closeView);

    }
    closeView(event, data) {
        this.state.show.set("c1");
    }
    changeView(component = "c1") {
        this.state.show.set(component);
    }

    //=============================================================
    // An important note is that the UI.render should has  the appState as argument,  
    // but this is ignored because each component has access to its own state
    // and already know where to look for render itself.
    //=============================================================
    render(state) {
            // just ignore the state argument
            if (this.state.show() == "c1") {
                return c1.render();
            }
            .
            .
            .
            .
            if(this.state.show() == "cn") {
                return cn.render();
            }
        }
   // =======================================================
   // in case that you want to use the immutable state
   //   (more mercury way also more safest)
   //  this will avoid to accidentally or by bad practices  change the state
   //  in the render procedure, if you know what are you doing 
   // just pick the method that you are comfortable.   
   // =======================================================
    render(state) {
        if (state.show == "c1") {
            return c1.render(state.c1);
        }
        .
        .
        .
        .
        if(this.state.show == "cn") {
            return cn.render(state.cn);
        }
    }
  }
  • if you make something like this.state.form_has_errors = true (in the c1 component), "the global re-render" will be fired.
  • For this has effect is important that the child states (or nodes of you observable tree) to be Observ-values, Obsev-Arrays, Observ-Struct, or Observ-Varhash, or some similar object.
  • you can access to you db model from the component using the global variable (this model also is a different observable tree).
  • also I will recommend you use EventEmmiter or EventEmmiter2 or any similar thing for communication between components ( to communicate events-things-stuff like Modal.onClose), just for avoid read or modify a state outside of its own component (this is more a preference).
  • you also can make you own observables structures and use them instead what comes with mercury
  • use getter (es6 ) for get your component states instead of directly access to them, also be careful when you want to modify the ui tree observable state (delete or add nodes or a sub-tree), the ideal is that you don't do this type of operation after the mercury app is started. always chose to use resetStates functions instead of deletion, recreation or addition of nodes

tips1: use typescript is of great help in this kind of cases

Sorry for my broken English I hope that this example can help you.

from mercury.

shoover avatar shoover commented on June 16, 2024

Thank you, @eightyeight and @criloz, for the helpful explanations. I can see there is room for changing designs to suit the application but the examples seem to do it one particular way that ensures a functional perspective. I see this separation enforced in many Elm designs, as well.

from mercury.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.