ofbiz-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "James Yong (Jira)" <j...@apache.org>
Subject [jira] [Updated] (OFBIZ-11409) POC for Dynamic Screen Using MVVM
Date Thu, 09 Apr 2020 16:26:00 GMT

     [ https://issues.apache.org/jira/browse/OFBIZ-11409?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]

James Yong updated OFBIZ-11409:
-------------------------------
    Description: 
Proof of concept for Model–view–viewmodel (MVVM) in form widgets.

Added data-bind attribute to the field, form and grid tag.

Example 1:

Go to [https://localhost:8443/humanres/control/NewEmployee] and try the following field:
 # First name
 # Middle name
 # Last name

Added Full Name field to demonstrate computed observable/property.

Example 2:

Page at [https://localhost:8443/ordermgr/control/ListQuoteItemsDemo?quoteId=CQ0001] duplicated
the functionality of Quote Items page, but done using data-binding way. 

mbrohl: here is a link to the discussion on the dev mailing list: [https://lists.apache.org/thread.html/r1cddbc8041e5a6559bfad979bc8570581a3d1f662a0f8692c7ee9e59%40%3Cdev.ofbiz.apache.org%3E]

*15th March 2020* 
 Updated the patch with more concrete examples for form and grid.

*10th April 2020*

Updated the patch with initVmFunc and some refactoring.

 

1) A javascript model function will be generated for the form / grid widgets when its data-bind
attribute is defined. 

2) First row of the grid is generated by the ofbiz renderer at the server side. Subsequent
rows will be generated by knockout at the browser side.

3) Naming convention of the viewmodel function is <Name of Form or Grid>*VmFunc*. There
is a viewmodel for the Grid widget at row level; naming convention is <Name of Grid>*VmRowFunc*.

4) Viewmodel function can be extended using javascript prototype. See the *.js.ftl files in
the patch. 

5) The following javascript files are used:
 * big/big.js - for basic mathematics operation
 * knockout/knockout-3.5.1.js - knockout library
 * knockout/knockout-config.js - extending the library and some code to configure knockout-secure-binding
 * knockout/knockout-secure-binding - allow knockout js to be used with a Content Security
Policy that disables eval and new Function.

6)  Example of hyperlink:

Before:
{code:xml}
<field name="quoteItemSeqId" title="${uiLabelMap.OrderOrderQuoteItemSeqId}" widget-style="buttontext"
use-when="${groovy: 'N'.equals(isPromo)}">
            <hyperlink description="${quoteItemSeqId}" target="EditQuoteItem" also-hidden="false">
                <parameter param-name="quoteId"/>
                <parameter param-name="quoteItemSeqId"/>
            </hyperlink>
        </field>
{code}
After:
{code:xml}
 <field name="quoteItemSeqId" title="${uiLabelMap.OrderOrderQuoteItemSeqId}"
               data-bind="text:quoteItemSeqId, attr: { href: editQuoteItemLink, title: 'Quote
Item Seq ID'}"
               widget-style="buttontext">
            <hyperlink description="[placeholder]"/>
        </field>
{code}
{code:javascript}
ListQuoteItemsDemoVmRowFunc.prototype = {
    computed: {
        "editQuoteItemLink": function(){
            return "<@ofbizUrl>EditQuoteItem?</@ofbizUrl>&quoteItemSeqId="
+ this.quoteItemSeqId() + "&quoteId=" + this.quoteId();
        },
   ...
};
{code}
>From the value of data-bind attribute, we can see that the href attribute points to the
editQuoteItemLink function.

editQuoteItemLink is a prototype member of ListQuoteItemsDemo*VmRowFunc* which is viewmodel
function for the Grid widget at row level.

7) Example of decimal places:
{code:javascript}
extend: {
        "quoteUnitPrice": {numeric: 2}
}
{code}
The column or field for qouteUnitPrice will be rounded to 2 decimal places.

8) Example of calculating line totals:
{code:xml}
 <field name="lineTotal" title="Line Total (Demo)" ><display/></field>
{code}
{code:javascript}
ListQuoteItemsDemoVmRowFunc.prototype = {
    computed: {
            ...
"lineTotal": function() {
            var itemPrice = this.quoteUnitPrice();
            var selectedAmount = this.selectedAmount() || 1;
            var quantity = this.quantity() || 0;
            return new Big(itemPrice).times(selectedAmount).times(quantity).toFixed(2);
        }
        ...
};
{code}

  was:
Proof of concept for Model–view–viewmodel (MVVM) in form widgets.

Added data-bind attribute to the field, form and grid tag.

Example 1:

Go to [https://localhost:8443/humanres/control/NewEmployee] and try the following field:
 # First name
 # Middle name
 # Last name

Added Full Name field to demonstrate computed observable/property.

Example 2:

Page at [https://localhost:8443/ordermgr/control/ListQuoteItemsDemo?quoteId=CQ0001] duplicated
the functionality of Quote Items page, but done using data-binding way. 

mbrohl: here is a link to the discussion on the dev mailing list: [https://lists.apache.org/thread.html/r1cddbc8041e5a6559bfad979bc8570581a3d1f662a0f8692c7ee9e59%40%3Cdev.ofbiz.apache.org%3E]

*15th March 2020* 
 Updated the patch with more concrete examples for form and grid.

1) A javascript viewmodel function will be generated for the form / grid widgets when its
data-bind attribute is defined. 

2) First row of the grid is generated by the ofbiz renderer at the server side. Subsequent
rows will be generated by knockout at the browser side.

3) Naming convention of the viewmodel is Vm<Name of Form or Grid>. There is a viewmodel
for the Grid widget at row level; naming convention is RowVm<Name of Grid>.

4) Viewmodel can be extended. See the *.js.ftl files in the patch. 

5) The following javascript files are used:
 * big/big.js - for basic mathematics operation
 * knockout/knockout-3.5.1.js - knockout library
 * knockout/knockout-config.js - extending the library and some code to configure knockout-secure-binding
 * knockout/knockout-secure-binding - allow knockout js to be used with a Content Security
Policy that disables eval and new Function.

6)  Example of hyperlink:

Before:
{code:xml}
<field name="quoteItemSeqId" title="${uiLabelMap.OrderOrderQuoteItemSeqId}" widget-style="buttontext"
use-when="${groovy: 'N'.equals(isPromo)}">
            <hyperlink description="${quoteItemSeqId}" target="EditQuoteItem" also-hidden="false">
                <parameter param-name="quoteId"/>
                <parameter param-name="quoteItemSeqId"/>
            </hyperlink>
        </field>
{code}
After:
{code:xml}
 <field name="quoteItemSeqId" title="${uiLabelMap.OrderOrderQuoteItemSeqId}"
               data-bind="text:quoteItemSeqId, attr: { href: editQuoteItemLink, title: 'Quote
Item Seq ID'}"
               widget-style="buttontext">
            <hyperlink description="[placeholder]"/>
        </field>
{code}
{code:javascript}
RowVmListQuoteItemsDemo.prototype = {
    computed: {
        "editQuoteItemLink": function(){
            return "<@ofbizUrl>EditQuoteItem?</@ofbizUrl>&quoteItemSeqId="
+ this.quoteItemSeqId() + "&quoteId=" + this.quoteId();
        },
   ...
};
{code}
>From the value of data-bind attribute, we can see that the href attribute points to the
editQuoteItemLink function.

editQuoteItemLink is a prototype member of RowVmListQuoteItemsDemo, while RowVmListQuoteItemsDemo
is viewmodel for the Grid widget at row level.

7) Example of decimal places:
{code:javascript}
extend: {
        "quoteUnitPrice": {numeric: 2}
}
{code}
The column or field for qouteUnitPrice will be rounded to 2 decimal places.

8) Example of calculating line totals:
{code:xml}
 <field name="lineTotal" title="Line Total (Demo)" ><display/></field>
{code}
{code:javascript}
RowVmListQuoteItemsDemo.prototype = {
    computed: {
            ...
"lineTotal": function() {
            var itemPrice = this.quoteUnitPrice();
            var selectedAmount = this.selectedAmount() || 1;
            var quantity = this.quantity() || 0;
            return new Big(itemPrice).times(selectedAmount).times(quantity).toFixed(2);
        }
        ...
};
{code}


> POC for Dynamic Screen Using MVVM
> ---------------------------------
>
>                 Key: OFBIZ-11409
>                 URL: https://issues.apache.org/jira/browse/OFBIZ-11409
>             Project: OFBiz
>          Issue Type: Improvement
>          Components: base
>    Affects Versions: Trunk
>            Reporter: James Yong
>            Assignee: James Yong
>            Priority: Minor
>             Fix For: Trunk
>
>         Attachments: OFBIZ-11409.patch, OFBIZ-11409.patch, OFBIZ-11409.patch, OFBIZ-11409.patch
>
>
> Proof of concept for Model–view–viewmodel (MVVM) in form widgets.
> Added data-bind attribute to the field, form and grid tag.
> Example 1:
> Go to [https://localhost:8443/humanres/control/NewEmployee] and try the following field:
>  # First name
>  # Middle name
>  # Last name
> Added Full Name field to demonstrate computed observable/property.
> Example 2:
> Page at [https://localhost:8443/ordermgr/control/ListQuoteItemsDemo?quoteId=CQ0001] duplicated
the functionality of Quote Items page, but done using data-binding way. 
> mbrohl: here is a link to the discussion on the dev mailing list: [https://lists.apache.org/thread.html/r1cddbc8041e5a6559bfad979bc8570581a3d1f662a0f8692c7ee9e59%40%3Cdev.ofbiz.apache.org%3E]
> *15th March 2020* 
>  Updated the patch with more concrete examples for form and grid.
> *10th April 2020*
> Updated the patch with initVmFunc and some refactoring.
>  
> 1) A javascript model function will be generated for the form / grid widgets when its
data-bind attribute is defined. 
> 2) First row of the grid is generated by the ofbiz renderer at the server side. Subsequent
rows will be generated by knockout at the browser side.
> 3) Naming convention of the viewmodel function is <Name of Form or Grid>*VmFunc*.
There is a viewmodel for the Grid widget at row level; naming convention is <Name of Grid>*VmRowFunc*.
> 4) Viewmodel function can be extended using javascript prototype. See the *.js.ftl files
in the patch. 
> 5) The following javascript files are used:
>  * big/big.js - for basic mathematics operation
>  * knockout/knockout-3.5.1.js - knockout library
>  * knockout/knockout-config.js - extending the library and some code to configure knockout-secure-binding
>  * knockout/knockout-secure-binding - allow knockout js to be used with a Content Security
Policy that disables eval and new Function.
> 6)  Example of hyperlink:
> Before:
> {code:xml}
> <field name="quoteItemSeqId" title="${uiLabelMap.OrderOrderQuoteItemSeqId}" widget-style="buttontext"
use-when="${groovy: 'N'.equals(isPromo)}">
>             <hyperlink description="${quoteItemSeqId}" target="EditQuoteItem" also-hidden="false">
>                 <parameter param-name="quoteId"/>
>                 <parameter param-name="quoteItemSeqId"/>
>             </hyperlink>
>         </field>
> {code}
> After:
> {code:xml}
>  <field name="quoteItemSeqId" title="${uiLabelMap.OrderOrderQuoteItemSeqId}"
>                data-bind="text:quoteItemSeqId, attr: { href: editQuoteItemLink, title:
'Quote Item Seq ID'}"
>                widget-style="buttontext">
>             <hyperlink description="[placeholder]"/>
>         </field>
> {code}
> {code:javascript}
> ListQuoteItemsDemoVmRowFunc.prototype = {
>     computed: {
>         "editQuoteItemLink": function(){
>             return "<@ofbizUrl>EditQuoteItem?</@ofbizUrl>&quoteItemSeqId="
+ this.quoteItemSeqId() + "&quoteId=" + this.quoteId();
>         },
>    ...
> };
> {code}
> From the value of data-bind attribute, we can see that the href attribute points to the
editQuoteItemLink function.
> editQuoteItemLink is a prototype member of ListQuoteItemsDemo*VmRowFunc* which is viewmodel
function for the Grid widget at row level.
> 7) Example of decimal places:
> {code:javascript}
> extend: {
>         "quoteUnitPrice": {numeric: 2}
> }
> {code}
> The column or field for qouteUnitPrice will be rounded to 2 decimal places.
> 8) Example of calculating line totals:
> {code:xml}
>  <field name="lineTotal" title="Line Total (Demo)" ><display/></field>
> {code}
> {code:javascript}
> ListQuoteItemsDemoVmRowFunc.prototype = {
>     computed: {
>             ...
> "lineTotal": function() {
>             var itemPrice = this.quoteUnitPrice();
>             var selectedAmount = this.selectedAmount() || 1;
>             var quantity = this.quantity() || 0;
>             return new Big(itemPrice).times(selectedAmount).times(quantity).toFixed(2);
>         }
>         ...
> };
> {code}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Mime
View raw message