Manage views with css or scopes in the Magiont Master

I am working on a page with many input controls and related sections. There are use cases on this page where I supposedly have to show / hide the div depending on how the user clicks on the input controls on different subsequent screens.

Now all the divs are on first load and by showing / hiding the screen changes for the user. Now to show / hide I can use css and add a class like * to the .main content div depending on the business logic.

eg:.

.main div{
  display: none;
 }
.main.view1 div.a,.main.view1 div.b,.main.view1 div.f{
  display:block;
 }

.main.view2 div.c,.main.view2 div.f {
  display:block;
 }
.main.view3 div.c,.main.view3 div.f {
  display:block;
 }

....etc

      

But in this way, no. css classes become unmanaged.

Please suggest if there is a better method I can use when it becomes easier to manage user flows. I think there are regions in the puppet that can help me deal with this. Please suggest a better way and clarify if the answer is marionette.regions

+3


source to share


1 answer


You can model your application as a state machine for modeling complex workflows.

To define a state machine:

  • Determine all the states your application might be in.
  • Determine the set of actions allowed in each state. Each action transfers the state of the application from one state to another.
  • Write business logic for each action that includes both permanent changes to the server and changing view state.

This schema is similar to creating a DFA , but you can add additional behavior according to your needs.

If this sounds too abstract, here's an example of a simple finite machine.

Let's say you are building a simple login application.

Constructing states and actions

  • INITIAL_STATE: The user visits the page for the first time and both fields are blank. Let's say you only want to make it username

    visible, but not password

    in this state. (Similar to the new Gmail workflow)

  • USERNAME_ENTRY_STATE: When the user enters the username and shows return

    , in this state, you want to display the username and hide the password. You can have onUsernameEntered

    as an action in this state.

  • PASSWORD_ENTRY_STATE: The username will now be hidden and the password view will be shown. When the user clicks return

    , you have to check if the usernames and passwords match. Let's call this actiononPasswordEntered

  • AUTHENTICATED_STATE: When the server checks the username and password combination, let's say you want to show the home page. Let's call this actiononAuthenticated

I just skipped the "Authentication Failed" operation.

Create views:

In this case, we have UsernameView

andPasswordView

Model design:

For our example, one model is sufficient Auth

.



Creating routes:

Check out the tips for managing routes with Marionette. The state machine must be initialized in the login path.

Example pseudocode:

I just showed the code related to state machine control. Rendering and event handling can be done as usual

var UsernameView = Backbone.View.extend({

    initialize: function(options) {
        this.stateMachine = options.stateMachine;
    },

    onUserNameEntered: function() {
         username = //get username from DOM;
         this.stateMachine.handleAction('onUserNameEntered', username)
    },

    show: function() {
       //write logic to show the view
    },

    hide: function() {
       //write logic to hide the view
    } 

});

var PasswordView = Backbone.View.extend({

    initialize: function(options) {
        this.stateMachine = options.stateMachine;
    },

    onPasswordEntered: function() {
         password = //get password from DOM;
         this.stateMachine.handleAction('onPasswordEntered', password)
    },

    show: function() {
       //write logic to show the view
    },

    hide: function() {
       //write logic to hide the view
    } 

});

      

Each state will have a function entry

that initializes the views and and a exit

function that will clean up the views. Each state will also have functions corresponding to the actual actions in that state. For example:

var BaseState = function(options) {
   this.stateMachine = options.stateMachine;
   this.authModel = options.authModel;
};

var InitialState = BaseState.extend({

    entry: function() {
        //show the username view
        // hide the password view
    },

    exit: function() {
       //hide the username view
    },

    onUsernameEntered: function(attrs) {
        this.authModel.set('username', attrs.username');
        this.stateMachine.setState('PASSWORD_ENTRY_STATE'); 
    }


});

      

Likewise, you can write code for other states.

Finally, the state machine:

var StateMachine = function() {
    this.authModel = new AuthModel;
    this.usernameView = new UserNameView({stateMachine: this});
    //and all the views

    this.initialState = new InitialState({authModel: this.authModel, usernameView: this.usernameView});
    //and similarly, all the states

    this.currentState = this.initialState;
};


StateMachine.prototype = {

    setState: function(stateCode) {
        this.currentState.exit(); //exit from currentState;
        this.currentState = this.getStateFromStateCode(stateCode);
        this.currentState.entry();  
    },

    handleAction: function(action, attrs) {
        //check if action is valid for current state
        if(actionValid) {
            //call appropriate event handler in currentState
        }
    }


};

StateMachine.prototype.constructor = StateMachine;

      

For a simple application, this seems to be overkill. For complex business logic, it's well worth the effort. This design pattern automatically prevents cases such as double-clicking on a button since you have already moved to the next state and the new state does not recognize the previous state action.

Once you've created a state machine, other members of your team can simply plug in their states and views, and see the big picture in one place.

Libraries like Redux show some of the heavy workloads shown here. As such, you might want to consider React + Redux + Immutable.js.

+3


source







All Articles