marko-js-archive / marko-widgets

[LEGACY] Module to support binding of behavior to rendered UI components rendered on the server or client
http://v3.markojs.com/docs/marko-widgets/
MIT License
141 stars 40 forks source link

Stateful Widget rerendering issue #57

Open baburammy opened 9 years ago

baburammy commented 9 years ago

I am trying to create stateful widget.

I have 14 different values in my json input, but only 6 values will change in client side. So I have decided to keep that 6 values in my state and use setState() method whenever needed. Real Data:-

 { 
 "secondsLeft":169200,
 "day":1,
 "hour":23,
 "minute":0,
 "second":55,
 "urgencyReached":false,

 "urgencyTime":3600,
 "counterStartTime":70,
 "label":"Ends in ", 
 "dayText":"day ",
 "hourText":"hrs ", 
 "minuteText":"mins ", 
 "secondText":"secs ",
 "sequence":["label","day","dayText","hour","hourText","minute","minuteText","second","secondText"]
 } 
getInitialState:function(input){
  return  { 
    "secondsLeft":input.secondsLeft,
    "day":input.day,
    "hour":input.hour,
    "minute":input.minute,
    "second":input.second,
    "urgencyReached":input.urgencyReached,
    };
}

getTemplateData:function(state,input){
     return  { 
        "secondsLeft":state.secondsLeft,
        "day":state.day,
        "hour":state.hour,
        "minute":state.minute,
        "second":state.second,
        "urgencyReached":state.urgencyReached,

        "urgencyTime":3600,
        "counterStartTime":70,
        "label":"Ends in ", 
        "dayText":"day ",
        "hourText":"hrs ", 
        "minuteText":"mins ", 
        "secondText":"secs ",
        "sequence":["label","day","dayText","hour","hourText","minute","minuteText","second","secondText"]
    };
}

But when It rerender, It doesn't send whole 14 input values in json to the template and It only send changed state values to the template.If I keep all the inputs in state ie..14 values, It is working fine. Kindly help me to solve this issue.

patrick-steele-idem commented 9 years ago

Hi @baburammy, I added a test case to see if I could reproduce the problem and I was unable to reproduce the problem. Can you provide a sample app to reproduce the problem? Do you see any problems with the test case I added? https://github.com/raptorjs/marko-widgets/commit/ddc65d1178e3bac825b6fa72f1b9ee5bc8248286

Please let me know if I am misunderstanding the problem that you are reporting. Thanks.

vl-ing commented 9 years ago

@patrick-steele-idem the problem we are trying to solve is to retain the initial state values in the rerender

For example like this, only the changed values are in the new state to rerender but the rest of the values that dont change should be from the get initial state of the template. But to achieve that the input is null when rerendering the widget.

getTemplateData:function(state,input){
     return  { 
        "secondsLeft":state.secondsLeft,
        "day":state.day,
        "hour":state.hour,
        "minute":state.minute,
        "second":state.second,
        "urgencyReached":state.urgencyReached,

       "urgencyTime":input.urgencyTime,
        "counterStartTime":input.counterStartTime,
        "label":input.label, 
        "dayText":input.day,
        "hourText": input.hourText, 
        "minuteText":input.minuteText, 
        "secondText":input.secondText,
        "sequence":input.sequence
    };
maberer commented 9 years ago

hi @vidya-lingineni

every time a widget is re-rendered due to a change in state, the getTemplateData() function is invoked with the new state provided by the "state" parameter.

When a widget is rendered for the first time, the input parameter contains the input parameters (that is useful for stateless widgets - as they never invoke the getTemplateData() function more than one time.

Everytime a stateful widget is re-rendered, the input parameter is empty (thats basicially the situation you are facing). Stateful widgets should therefore only read from the state parameter.

In your getInitialState() function you should write every stateful property from the input parameter to the object this function returns. The getInitialState() function should then only consume these properties by reading them from the state parameter.

Hope that clarifies the situation - thanks for your interest in marko!

vl-ing commented 9 years ago

@tindli Thanks for the reply.

The model is nested with many levels. It is not practical to keep all the properties as single level. So for any unchanged properties if we keep the object like below example in state, the widget is getting rerendered again even though state is not changed. Because its just doing object == object

Example:

placebidAction": {
      "textSpans": [
        {
          "text": "Place max bid"
        }
      ],
      "action": {
        "actionType": "NAV",
        "URL": "http: //www.ebay.com"
      }
    }