#How to make Hierarchical GUI Components and Applications (1/3)
Original Posts
http://jinjor-labo.hatenablog.com/entry/2013/12/08/221003
http://jinjor-labo.hatenablog.com/entry/2013/12/10/094825
http://jinjor-labo.hatenablog.com/entry/2013/12/12/225955
##Introduction
Recently, many developers try to make rich clinent web applications by means of JavaScript. And they want to make them more smarter ways. and of cource I do too :) I tried many kinds of JavaScript MVC frameworks and finally came to an idea.
Assumptions
- We wants to make business-like systems.(Not games or web sites)
- We don't aim to use this idea right now, since we have no sufficeient libraries.
##Constructing UI Components hierarchically
Some libraries like AngularJS or Specifications like Web Components make it possible to define custom elements and use it as same as other HTML elements. Don't you think it a good idea!? Yes, but not so special. It's a common idea for constructing larger things using small parts.
In any case, you like that idea and then try it. The following figure indicates a typical UI which has a selector for something on the left and a viewer showing the details for it on the right.
Note that this shows not an inheritance relationship but one of posession. Each component has its child components. They must keep ignorant of their neighbors and parents. The higher-located components listen to their chilren's events and then update others. It may be similar if you use jQuery, but the roles of components are much clearer.
##Ok, it's the best practice. Right?
No. It seems to be the best way in most cases, but some more complicated example show the difficalty of applying that simple idea. Here is an example.
By some serious needs, you have to register persons and calculate the total amount of money they paid.
// イベントを受け取り
var memverView = new MemberView().on("change", updateSubmitView);
memberViewList.add(memverView);
function updateSubmitView(){
var memberList = memberViewList.map(function(view){
return view.member;
});
submitView.update(memberList);// データを渡す
}
There exist a memberViewList
and a submitView
in your code. Their roles are carefully separated and the implamentations are encapsulated in case of changing the spec.
But the future is always unpredictable. The new spec requires:
- If a member paid 50% away from the avarage, his view must be colored by red.
- When at least one such person exists, the submit button must be disabled.
Then the new code is as follows...
var memverView = new MemberView().on("change", updateSubmitView);
memberViewList.add(memverView);
function updateSubmitView(){
var memberList = memberViewList.map(function(memberView){
return memberView.member;
});
submitView.update(memberList);
var sum = submitView.getSum();
memberViewList.forEach(function(memberView){
memberView.updateBySum(sum);
});
var errorFlg = false;
memberViewList.forEach(function(memberView){
errorFlg = errorFlg || memberView.getErrorFlg();
});
submitView.updateByErrorFlg(errorFlg);
}
What the hell? The data is always comming and going between two views. Do you say that's the OOP way to solve the ploblem?
##Hello, model-driven world.
The worst idea is that each view holds its data respectively, which makes their parent work hard to synchronize their data. Is that mean that separating components is evil? No, but there are some ways to share the single Model by multi Views. The abstraction of this idea is as follows.
The Views subscribe the change of Model and update themselves. This behavior is common of other nodes of the whole tree. My ideal world works like that.
Next: How to implement this?