You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Mark Lundquist <ml...@wrinkledog.com> on 2005/06/21 07:48:23 UTC

[CForms binding] access to model data from repeater row widget

Hi,

Here is a scenario that I keep finding myself dealing with...

Some repeater is bound to a collection, and also contains one or more 
widgets that are not bound to the collection elements.  For instance, 
there might be a checkbox that means "do something to/with the thing in 
this row".  After accepting the form, the processing entails iterating 
through the rows and doing something something with the corresponding 
object from the model layer, which means I need to be able to 
find/access that object.

It seems like each time, I come up with some different way of handling 
this, and none of them ever feels quite right.

Then I thought, if the binding framework would decorate each repeater 
row widget with a property that references the bound object, things 
would just be a lot cleaner.

So I made this trivial change, and it works great.  The repeater rows 
now have a "model" property that references the model object to which 
that row is bound.  I tweaked the JXTG macro version of the template 
engine so that I can reference "${model_}" from within the 
<ft:repeater-widget>.  That is really handy, because it lets me avoid 
having to specify a bunch of output widgets in the the form definition 
+ binding.  What I really had in mind with this change, though, was 
making the flowscript easier, and it does do that... but currently in 
the flow I have to unwrap() the repeater row widget by hand before I 
can call getModel() on it, so before I finalize this I want to add that 
to the Form flow API.  Then I think it will be just right.

However...

I realized that I have a nomenclature clash with my choice of the name 
"model".  I've been using the v2 API for a long time, so I forgot in 
v1, there is a Form.model property that denotes the widget value tree.  
So I don't want to cause confusion with another sense of "model"... it 
should be called something else.  "rowData"?  "rowObject"?  WDYT?

please advise! :-)
—ml—
  

Re: [CForms binding] access to model data from repeater row widget

Posted by Sylvain Wallez <sy...@apache.org>.
Mark Lundquist wrote:

>
> Hi Sylvain, thx for your reply...
>
>>  ....
>>
>>>         However...
>>>
>>>>>         I realized that I have a nomenclature clash with my choice of
>>>>>         the name "model". I've been using the v2 API for a long time,
>>>>>         so I forgot in v1, there is a Form.model property that 
>>>>> denotes
>>>>>         the widget value tree.
>>>>
>>>>
>>>>     The "model" property is only available on the toplevel form JS
>>>>     object, so there may not be a clash.
>>>
>>>
>>> It's not a hard "name clash", but it is a nomenclature clash in that 
>>> it's a different sense of the term "model". My new row "model" 
>>> property is truly the "model", as in "MVC" or as in 
>>> "loadFormFromModel()". The v1 "model" is "model" in terms of 
>>> "formmodel", I guess. I just think it's too confusing to have both 
>>> senses. I actually sort of wish the v1 "model" were called something 
>>> else, because it isn't the model /a la/ MVC.
>>
>>
>> You're right. The "form.model" is actually the value tree.
>
>
> Maybe form.model should be renamed to "form.value"!  Then you would 
> have these two expressions that mean the same thing (just as they look 
> like they should! :-):
>
>     form.value.foobar
>
> and
>
>     form.lookupWidget('foobar').value
>
> , right? :-)


Yes, and also "form.value.foo.bar.baz" and 
"form.lookupWidget('foo/bar/baz').value". Naming it "form.values" 
(plural) sounds better.

> But for now in my working version of the code I settled on "rowModel" 
> to expose the row model object in Flowscript and JXT.
>
> Now then, the following exchange has me totally confused:
>
>>>>     It doesn't seem good to me to provide at the API level a way to
>>>>     link the form to the data model,
>>>
>>>
>>> No, no, it /is/ good... :-)
>>> [ ...my rambling snipped...]
>>>
>>>>     However, there are some uses cases where this makes sense. You can
>>>>     then use widget attributes (see get/setAttribute) to attach some
>>>>     application data of your liking to any widget, including repeater
>>>>     rows.
>>>
>>>
>>> See, that's the problem, this is what I have to deal with currently 
>>> :-)... I have two parallel structures: a Collection, and a Repeater. 
>>> If the Repeater does not give me a "view" to its collection, then I 
>>> have to do some kind of iteration to create associations somewhere 
>>> between the repeater rows and the collection elements, and this just 
>>> feels silly and wasteful. I've done it this way, decorating the 
>>> repeater rows with handles to the model data, and I just think that 
>>> since the binding layer is already iterating across the collection, 
>>> it should do this decoration for me! :-).
>>
>>
>> Yes. That's the idea behind the "bound repeater binding" idea 
>> Reinhard pointed to.
>
>
> Right.  Which was your idea, and which I think I have gone and 
> implemented before I knew that somebody else had thought of it :-)...  
> Or have I not?  Maybe I am misunderstanding Reinhard's reference and 
> it isn't really the same thing... or maybe you are misunderstanding 
> me, and thinking it's not the same thing, but it really _is_? :-)
>
> Are you saying, "Ah yes, you're right... I thought of this before, and 
> now I remember why it _is_ a good idea (+1! :-)" ?
>
> Or — are you saying "Ah, it looks like I did think of this too once, 
> but now on second thought I'm not so sure it was a good idea" ?


LOL! I of course remember this was my idea, and I still think it is good.

What doesn't seem good however, is to provide a way to link the data 
model and the form, _without going through the binding_. It is ok for 
some bindings to use widgets attributes are storage areas for their 
stuff, but it isn't ok IMO for the _widget_ API to know about 
application data.

>>> I could live with there being a "callback" facility in the repeater 
>>> binding language, e.g. <fb:javascript> within <fb:on-bind>... know 
>>> what I mean? But that's sort of beyond my ability to implement, and 
>>> I was looking for something that I could actually do :-)
>>
>>
>> Extending the repeater binding to keep the connection to the data 
>> model may be easier, no?
>
>
> Well, it certainly was awfully easy :-)  Tell you what, the change is 
> so ridiculously small, I'll just attach the diffs  (they are against 
> src/blocks/forms/java/org/apache/cocoon/forms) and you can see if 
> we're talking about the same thing.  At first this amounted to about 6 
> lines of code added, before I added the convenience flowscript 
> function (that I had mentioned in the original post that I wanted to 
> add... this doubled :-) the size of the mod).  BTW, this function — 
> 'getRowModel()' — I only added it in v2 ('cuz that's what I'm using! 
> :-).  When I looked at v1's ScriptableWidget, I hesitated when I saw 
> that there are so few javascript functions defined there, and I wasn't 
> sure if this is really the right idiom for v1... Care to comment?


Well, this is exactly what I consider as wrong above :-)

That's the binding job to possibly use widget attributes to store data 
that helps later on the form's save. But the form itself shouldn't have 
to care about it.

So the changes should be in RepeaterBinding, and not in Repeater itself.

Sylvain

-- 
Sylvain Wallez                        Anyware Technologies
http://apache.org/~sylvain            http://anyware-tech.com
Apache Software Foundation Member     Research & Technology Director


Re: [CForms binding] access to model data from repeater row widget

Posted by Mark Lundquist <ml...@wrinkledog.com>.
Hi Sylvain, thx for your reply...

>  ....
>>         However...
>>
>>>>         I realized that I have a nomenclature clash with my choice 
>>>> of
>>>>         the name "model". I've been using the v2 API for a long 
>>>> time,
>>>>         so I forgot in v1, there is a Form.model property that 
>>>> denotes
>>>>         the widget value tree.
>>>
>>>     The "model" property is only available on the toplevel form JS
>>>     object, so there may not be a clash.
>>
>> It's not a hard "name clash", but it is a nomenclature clash in that 
>> it's a different sense of the term "model". My new row "model" 
>> property is truly the "model", as in "MVC" or as in 
>> "loadFormFromModel()". The v1 "model" is "model" in terms of 
>> "formmodel", I guess. I just think it's too confusing to have both 
>> senses. I actually sort of wish the v1 "model" were called something 
>> else, because it isn't the model /a la/ MVC.
>
> You're right. The "form.model" is actually the value tree.

Maybe form.model should be renamed to "form.value"!  Then you would 
have these two expressions that mean the same thing (just as they look 
like they should! :-):

	form.value.foobar

and

	form.lookupWidget('foobar').value

, right? :-)

But for now in my working version of the code I settled on "rowModel" 
to expose the row model object in Flowscript and JXT.

Now then, the following exchange has me totally confused:

>>>     It doesn't seem good to me to provide at the API level a way to
>>>     link the form to the data model,
>>
>> No, no, it /is/ good... :-)
>> [ ...my rambling snipped...]
>>
>>>     However, there are some uses cases where this makes sense. You 
>>> can
>>>     then use widget attributes (see get/setAttribute) to attach some
>>>     application data of your liking to any widget, including repeater
>>>     rows.
>>
>> See, that's the problem, this is what I have to deal with currently 
>> :-)... I have two parallel structures: a Collection, and a Repeater. 
>> If the Repeater does not give me a "view" to its collection, then I 
>> have to do some kind of iteration to create associations somewhere 
>> between the repeater rows and the collection elements, and this just 
>> feels silly and wasteful. I've done it this way, decorating the 
>> repeater rows with handles to the model data, and I just think that 
>> since the binding layer is already iterating across the collection, 
>> it should do this decoration for me! :-).
>
> Yes. That's the idea behind the "bound repeater binding" idea Reinhard 
> pointed to.

Right.  Which was your idea, and which I think I have gone and 
implemented before I knew that somebody else had thought of it :-)...  
Or have I not?  Maybe I am misunderstanding Reinhard's reference and it 
isn't really the same thing... or maybe you are misunderstanding me, 
and thinking it's not the same thing, but it really _is_? :-)

Are you saying, "Ah yes, you're right... I thought of this before, and 
now I remember why it _is_ a good idea (+1! :-)" ?

Or — are you saying "Ah, it looks like I did think of this too once, 
but now on second thought I'm not so sure it was a good idea" ?

>> I could live with there being a "callback" facility in the repeater 
>> binding language, e.g. <fb:javascript> within <fb:on-bind>... know 
>> what I mean? But that's sort of beyond my ability to implement, and I 
>> was looking for something that I could actually do :-)
>
> Extending the repeater binding to keep the connection to the data 
> model may be easier, no?

Well, it certainly was awfully easy :-)  Tell you what, the change is 
so ridiculously small, I'll just attach the diffs  (they are against 
src/blocks/forms/java/org/apache/cocoon/forms) and you can see if we're 
talking about the same thing.  At first this amounted to about 6 lines 
of code added, before I added the convenience flowscript function (that 
I had mentioned in the original post that I wanted to add... this 
doubled :-) the size of the mod).  BTW, this function — 'getRowModel()' 
— I only added it in v2 ('cuz that's what I'm using! :-).  When I 
looked at v1's ScriptableWidget, I hesitated when I saw that there are 
so few javascript functions defined there, and I wasn't sure if this is 
really the right idiom for v1... Care to comment?

Cheers,
—ml—

Re: [Cforms] "selectability" intrinsic to RepeaterRow? (was Re: [CForms binding] access to model data from repeater row widget)

Posted by Sylvain Wallez <sy...@apache.org>.
Mark Lundquist wrote:

> On Jun 22, 2005, at 2:17 AM, Sylvain Wallez wrote:
>
>> Mark Lundquist wrote:
>>
>>> On Jun 20, 2005, at 11:42 PM, Sylvain Wallez wrote:
>>> [8<----snip!----]
>>>
>>>>     And even more, repeater actions could have constraints on the
>>>>     selection size, such as single-selection, multiple-selection,
>>>>     leading these actions to be disabled if their associated
>>>>     constraint isn't met.
>>>
>>>
>>> ...or a validation error. Like the classic "you must choose at least 
>>> one" constraint.
>>>
>> Not sure this is a validation error. In the case of actions this 
>> should be more a transient message (e.g. a popup).
>
>
> D'oh, my bad... I missed that you are talking about repeater 
> _actions_.  Gotta read slower...
>
> Anyway, that is a good idea.  And be that as it may... I would also 
> like automatic validation for the "must choose at least one" scenario, 
> because I've had to code it by hand — gee, probably _twice_ now! :-).  
> In my book, that calls for automation! :-)  Anyway, if selectedness 
> were made intrinsic as you propose, then that would enable this 
> validation.


Definitely.

> Actually, I guess as "at least one" is the range [1..], we should 
> support the more general 'range' validation criterion here.  Maybe we 
> can generalize <fd:value-count> for this?


Hmm... value-count is currently testing the number of values of the 
widget it is attached to, and in that case it would test the repeater 
attached to the action widget...

Also, an action's validators are more rules defining the availability of 
the action, and should therefore be evaluated earlier than validations, 
to provide better user feedback, as a disabled button is better than an 
enabled one that pops up a "you can't do that" when you click on it. On 
the other hand, this feedback should be computed on the client-side to 
ensure action's availability isntantly reflect the state of selected rows.

Hmm... need to think more about it...

>>  That isn't persisted across successive posts of a form. Now we may 
>> consider that actions have a special way of handling validation 
>> errors by clearing them at each readFromRequest() which is different 
>> from other widget types.
>>
>>>>     And finally, we may be able to specify on repeater bindings if
>>>>     they have to act on the whole repeater on just on the selection.
>>>
>>>
>>> Not sure what you mean, can you give an example?
>>
>>
>> The idea is to specify in the binding if it should operate on the 
>> full repeater or only on the selected rows. Something like:
>> <fb:repeater use-selection="true">
>
>
> Right :-)  But it does sound like it could lead to usability issues 
> (error-prone form designs).  I'm having trouble thinking of where 
> use-selection="true" in a binding would be actually useful...?


What about filling a shopping cart from a repeater showing a list of 
articles, keeping only the selected ones?

Sylvain

-- 
Sylvain Wallez                        Anyware Technologies
http://apache.org/~sylvain            http://anyware-tech.com
Apache Software Foundation Member     Research & Technology Director


[Cforms] "selectability" intrinsic to RepeaterRow? (was Re: [CForms binding] access to model data from repeater row widget)

Posted by Mark Lundquist <ml...@wrinkledog.com>.
On Jun 22, 2005, at 2:17 AM, Sylvain Wallez wrote:

> Mark Lundquist wrote:
>> On Jun 20, 2005, at 11:42 PM, Sylvain Wallez wrote:
>> [8<----snip!----]
>>
>>>     And even more, repeater actions could have constraints on the
>>>     selection size, such as single-selection, multiple-selection,
>>>     leading these actions to be disabled if their associated
>>>     constraint isn't met.
>>
>> ...or a validation error. Like the classic "you must choose at least 
>> one" constraint.
>>
> Not sure this is a validation error. In the case of actions this 
> should be more a transient message (e.g. a popup).

D'oh, my bad... I missed that you are talking about repeater _actions_. 
  Gotta read slower...

Anyway, that is a good idea.  And be that as it may... I would also 
like automatic validation for the "must choose at least one" scenario, 
because I've had to code it by hand — gee, probably _twice_ now! :-).  
In my book, that calls for automation! :-)  Anyway, if selectedness 
were made intrinsic as you propose, then that would enable this 
validation.

Actually, I guess as "at least one" is the range [1..], we should 
support the more general 'range' validation criterion here.  Maybe we 
can generalize <fd:value-count> for this?

>  That isn't persisted across successive posts of a form. Now we may 
> consider that actions have a special way of handling validation errors 
> by clearing them at each readFromRequest() which is different from 
> other widget types.
>
>>>     And finally, we may be able to specify on repeater bindings if
>>>     they have to act on the whole repeater on just on the selection.
>>
>> Not sure what you mean, can you give an example?
>
> The idea is to specify in the binding if it should operate on the full 
> repeater or only on the selected rows. Something like:
> <fb:repeater use-selection="true">

Right :-)  But it does sound like it could lead to usability issues 
(error-prone form designs).  I'm having trouble thinking of where 
use-selection="true" in a binding would be actually useful...?

best regards,
—ml—


Re: [CForms binding] access to model data from repeater row widget

Posted by Sylvain Wallez <sy...@apache.org>.
Mark Lundquist wrote:

>
>
> On Jun 20, 2005, at 11:42 PM, Sylvain Wallez wrote:
>
>     So in essence, you want to act on the selected rows, right?
>
>
> Yup.
>
>     I encountered this already, and I've been thinking to explicitely
>     add the selection concept to repeaters. That selection would be
>     defined by a boolean field present on each row.
>
>
> Great idea. That is orthogonal to what I've done... you are saying 
> "selection is an intrinsic aspect of rows", and I'm saying "I need a 
> handle on the data".


Yeah, right :-)

>     Note that a boolean field doesn't necessarily means rendering as a
>     checkbox. It can also be some highlighting of selected rows.
>
>
> Yup.
>
>
>     That would lead to
>     <fd:repeater name="repeater" selection="select">
>     <fd:widgets>
>     <fd:field id="name"/>
>     <fd:booleanfield id="select"/>
>     </fd:widgets>
>     </fd:repeater>
>
>     Repeater actions such as "delete-rows" would then no more have a
>     need to be given the select widget's name as of today.
>
> +1
>
>     And even more, repeater actions could have constraints on the
>     selection size, such as single-selection, multiple-selection,
>     leading these actions to be disabled if their associated
>     constraint isn't met.
>
> ...or a validation error. Like the classic "you must choose at least 
> one" constraint.


Not sure this is a validation error. In the case of actions this should 
be more a transient message (e.g. a popup). That isn't persisted across 
successive posts of a form. Now we may consider that actions have a 
special way of handling validation errors by clearing them at each 
readFromRequest() which is different from other widget types.

>     And finally, we may be able to specify on repeater bindings if
>     they have to act on the whole repeater on just on the selection.
>
> Not sure what you mean, can you give an example?


The idea is to specify in the binding if it should operate on the full 
repeater or only on the selected rows. Something like:
<fb:repeater use-selection="true">
  ....

>         However...
>
>         I realized that I have a nomenclature clash with my choice of
>         the name "model". I've been using the v2 API for a long time,
>         so I forgot in v1, there is a Form.model property that denotes
>         the widget value tree.
>
>
>
>     The "model" property is only available on the toplevel form JS
>     object, so there may not be a clash.
>
>
> It's not a hard "name clash", but it is a nomenclature clash in that 
> it's a different sense of the term "model". My new row "model" 
> property is truly the "model", as in "MVC" or as in 
> "loadFormFromModel()". The v1 "model" is "model" in terms of 
> "formmodel", I guess. I just think it's too confusing to have both 
> senses. I actually sort of wish the v1 "model" were called something 
> else, because it isn't the model /a la/ MVC.


You're right. The "form.model" is actually the value tree.

>     BTW, why do you prefer v2 rather than v1?
>
>         So I don't want to cause confusion with another sense of
>         "model"... it should be called something else. "rowData"?
>         "rowObject"? WDYT?
>
>
>     It doesn't seem good to me to provide at the API level a way to
>     link the form to the data model,
>
>
> No, no, it /is/ good... :-)
>
>     as this is something that isn't suitable for all situations (think
>     transactional systems, heavyweight objects, etc).
>
>
> OK, for what percentage of real-life applications would you say it is 
> unsuitable? If it's 10-20%, then do we want to penalize the other 
> 80-90%? I don't deny those situations exist, but I think they are less 
> common, and in those cases my instinct would be to use a DTO at some 
> level instead of binding directly to the model object. My instinct 
> would not be to say, "ah, now /here/ is why we don't provide a handle 
> from repeater rows to their bound data!" :-) One thing I've found to 
> work really well is to build an /ad hoc/ DTO right in the flowscript 
> as a javascript object, which looks to the binding framework just like 
> a Java bean.
>
> Another way to say it: adding this repeater row decoration doesn't 
> break any isolation between layers of the application. It breaks an 
> undesirable isolation within a single layer (the form definition, 
> binding and flowscript all live in the UI layer). The degree of 
> isolation between the UI layer and the model, in turn, depends on what 
> is given to the UI layer. If that is a live model object, then the 
> isolation is already broken, and that may or may not be a bad thing, 
> but that concern doesn't belong to the internal architecture of CForms 
> (IMHO... just trying to state a case here :-).
>
> This is making me think of a discussion in "Hibernate in Action"... In 
> the chapter "Writing Layered Applications", there's a section entitled 
> "Rethinking DTOs". The authors make the case that the dogma "you 
> should never have live model objects in the view layer" is extreme 
> (maybe it is "quaint and outmoded", like someone in the butthead 
> government of my country has said about the Geneva convention :-/). 
> Anyway... it's not quite what we're talking about here, but it's related.
>
>     And one of the big strengths of CForms is its strong isolation
>     with the data model while the user is messing around with input
>     values.
>
>
> Hmm, well you can't modify the data from JXTemplate, or at least the 
> mechanisms are not well-known ;-/ (and maybe JXT is too strong :-)... 
> in any case, I think most people really are interested in using JXT as 
> just a template engine, not in programming in JXT :-). That leaves the 
> flowscript, and you can already have your way with the model data from 
> flowscript if the live data is what the services layer provides...
>
>     However, there are some uses cases where this makes sense. You can
>     then use widget attributes (see get/setAttribute) to attach some
>     application data of your liking to any widget, including repeater
>     rows.
>
>
> See, that's the problem, this is what I have to deal with currently 
> :-)... I have two parallel structures: a Collection, and a Repeater. 
> If the Repeater does not give me a "view" to its collection, then I 
> have to do some kind of iteration to create associations somewhere 
> between the repeater rows and the collection elements, and this just 
> feels silly and wasteful. I've done it this way, decorating the 
> repeater rows with handles to the model data, and I just think that 
> since the binding layer is already iterating across the collection, it 
> should do this decoration for me! :-).


Yes. That's the idea behind the "bound repeater binding" idea Reinhard 
pointed to.

> I could live with there being a "callback" facility in the repeater 
> binding language, e.g. <fb:javascript> within <fb:on-bind>... know 
> what I mean? But that's sort of beyond my ability to implement, and I 
> was looking for something that I could actually do :-)


Extending the repeater binding to keep the connection to the data model 
may be easier, no?

> As Reinhard pointed out, you've already proposed my patch:
>
> / "Another option to ease repeater binding could be to attach the loaded
> data as attributes in the widget row, thus giving instant access to that
> data at save time."/
> (http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=109950611823830&w=2)/
> /


:-)

Sylvain

-- 
Sylvain Wallez                        Anyware Technologies
http://apache.org/~sylvain            http://anyware-tech.com
Apache Software Foundation Member     Research & Technology Director


Re: [CForms binding] access to model data from repeater row widget

Posted by Mark Lundquist <ml...@wrinkledog.com>.
On Jun 20, 2005, at 11:42 PM, Sylvain Wallez wrote:

> So in essence, you want to act on the selected rows, right?

Yup.

> I encountered this already, and I've been thinking to explicitely add 
> the selection concept to repeaters. That selection would be defined by 
> a boolean field present on each row.

Great idea.  That is orthogonal to what I've done... you are saying 
"selection is an intrinsic aspect of rows", and I'm saying "I need a 
handle on the data".

>  Note that a boolean field doesn't necessarily means rendering as a 
> checkbox. It can also be some highlighting of selected rows.

Yup.

>
> That would lead to
> <fd:repeater name="repeater" selection="select">
>  <fd:widgets>
>    <fd:field id="name"/>
>    <fd:booleanfield id="select"/>
>  </fd:widgets>
> </fd:repeater>
>
> Repeater actions such as "delete-rows" would then no more have a need 
> to be given the select widget's name as of today.
+1

> And even more, repeater actions could have constraints on the 
> selection size, such as single-selection, multiple-selection, leading 
> these actions to be disabled if their associated constraint isn't met.
...or a validation error.  Like the classic "you must choose at least 
one" constraint.

>
> And finally, we may be able to specify on repeater bindings if they 
> have to act on the whole repeater on just on the selection.
Not sure what you mean, can you give an example?

>> However...
>>
>> I realized that I have a nomenclature clash with my choice of the 
>> name "model". I've been using the v2 API for a long time, so I forgot 
>> in v1, there is a Form.model property that denotes the widget value 
>> tree.
>
>
> The "model" property is only available on the toplevel form JS object, 
> so there may not be a clash.

It's not a hard "name clash", but it is a nomenclature clash in that 
it's a different sense of the term "model".  My new row "model" 
property is truly the "model", as in "MVC" or as in 
"loadFormFromModel()".  The v1 "model" is "model" in terms of 
"formmodel", I guess.  I just think it's too confusing to have both 
senses.  I actually sort of wish the v1 "model" were called something 
else, because it isn't the model a la MVC.

>  BTW, why do you prefer v2 rather than v1?
>
>> So I don't want to cause confusion with another sense of "model"... 
>> it should be called something else. "rowData"? "rowObject"? WDYT?
>
> It doesn't seem good to me to provide at the API level a way to link 
> the form to the data model,

No, no, it is good... :-)

>  as this is something that isn't suitable for all situations (think 
> transactional systems, heavyweight objects, etc).

OK, for what percentage of real-life applications would you say it is 
unsuitable?  If it's 10-20%, then do we want to penalize the other 
80-90%?  I don't deny those situations exist, but I think they are less 
common, and in those cases my instinct would be to use a DTO at some 
level instead of binding directly to the model object.  My instinct 
would not be to say, "ah, now here is why we don't provide a handle 
from repeater rows to their bound data!" :-)  One thing I've found to 
work really well is to build an ad hoc DTO right in the flowscript as a 
javascript object, which looks to the binding framework just like a 
Java bean.

Another way to say it: adding this repeater row decoration doesn't 
break any isolation between layers of the application.  It breaks an 
undesirable isolation within a single layer (the form definition, 
binding and flowscript all live in the UI layer).  The degree of 
isolation between the UI layer and the model, in turn, depends on what 
is given to the UI layer.  If that is a live model object, then the 
isolation is already broken, and that may or may not be a bad thing, 
but that concern doesn't belong to the internal architecture of CForms 
(IMHO... just trying to state a case here :-).

This is making me think of a discussion in "Hibernate in Action"... In 
the chapter "Writing Layered Applications", there's a section entitled 
"Rethinking DTOs".  The authors make the case that the dogma "you 
should never have live model objects in the view layer" is extreme 
(maybe it is "quaint and outmoded", like someone in the butthead 
government of my country has said about the Geneva convention :-/).  
Anyway... it's not quite what we're talking about here, but it's 
related.

> And one of the big strengths of CForms is its strong isolation with 
> the data model while the user is messing around with input values.

Hmm, well you can't modify the data from JXTemplate, or at least the 
mechanisms are not well-known ;-/ (and maybe JXT is too strong :-)... 
in any case, I think most people really are interested in using JXT as 
just a template engine, not in programming in JXT :-).  That leaves the 
flowscript, and you can already have your way with the model data from 
flowscript if the live data is what the services layer provides...

> However, there are some uses cases where this makes sense. You can 
> then use widget attributes (see get/setAttribute) to attach some 
> application data of your liking to any widget, including repeater 
> rows.

See, that's the problem, this is what I have to deal with currently 
:-)...  I have two parallel structures: a Collection, and a Repeater.  
If the Repeater does not give me a "view" to its collection, then I 
have to do some kind of iteration to create associations somewhere 
between the repeater rows and the collection elements, and this just 
feels silly and wasteful.  I've done it this way, decorating the 
repeater rows with handles to the model data, and I just think that 
since the binding layer is already iterating across the collection, it 
should do this decoration for me! :-).

I could live with there being a "callback" facility in the repeater 
binding language, e.g. <fb:javascript> within <fb:on-bind>... know what 
I mean?  But that's sort of beyond my ability to implement, and I was 
looking for something that I could actually do :-)

As Reinhard pointed out, you've already proposed my patch:

	"Another option to ease repeater binding could be to attach the loaded
	data as attributes in the widget row, thus giving instant access to 
that
	data at save time."
		(http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=109950611823830&w=2)

I've gotta do a better job of keeping up on the dev list... :-)
—ml—


Re: v2 (was Re: [CForms binding] access to model data from repeater row widget)

Posted by Sylvain Wallez <sy...@apache.org>.
Mark Lundquist wrote:

> Hey, this morning I remembered what started me down the v2 path, as I  
> was replying to a guy on the users' list.  It was that in v2, I can 
> set  someWidget.onValidate to a function that is nested inside the 
> form  controller flowscript function, where it can access that 
> function's  local variables.  (Here's that mail:  
> http://marc.theaimsgroup.com/?l=xml-cocoon- 
> users&m=111954841402175&w=2... I mention a way that might work in v1  
> that I hadn't thought of until today as I was composing that!)


Ah yes. I'll add this to V1 as well.

Sylvain


-- 
Sylvain Wallez                        Anyware Technologies
http://apache.org/~sylvain            http://anyware-tech.com
Apache Software Foundation Member     Research & Technology Director


Re: v2 (was Re: [CForms binding] access to model data from repeater row widget)

Posted by Mark Lundquist <ml...@wrinkledog.com>.
On Jun 23, 2005, at 2:25 AM, Sylvain Wallez wrote:

>> One thing I don't care so much for in v2 is the idiom of attaching  
>> view data as properties of the widget tree root.  The minimalist  
>> approach (losing 'bizData') was clever, but in actual practice I find  
>> that I really like having one locus of transfer of data between the  
>> flowscript and the presentation, so I usually end up with something  
>> like this anyway:
>>
>>     w.viewData =
>>         {
>>             schtuff:     foobar,
>>             etc:        otherStuff
>>         };
>>     form.showForm ('whatev');
>
> Uh? Didn't knew about that, and looks hacky IMO.

Ex-hacktly! :-)

>>     BTW, why do you prefer v2 rather than v1?

Hey, this morning I remembered what started me down the v2 path, as I  
was replying to a guy on the users' list.  It was that in v2, I can set  
someWidget.onValidate to a function that is nested inside the form  
controller flowscript function, where it can access that function's  
local variables.  (Here's that mail:  
http://marc.theaimsgroup.com/?l=xml-cocoon- 
users&m=111954841402175&w=2... I mention a way that might work in v1  
that I hadn't thought of until today as I was composing that!)

cheers,
—ml—


Re: v2 (was Re: [CForms binding] access to model data from repeater row widget)

Posted by Sylvain Wallez <sy...@apache.org>.
Mark Lundquist wrote:

>
> On Jun 21, 2005, at 8:41 AM, Mark Lundquist wrote:
>
>>
>> On Jun 20, 2005, at 11:42 PM, Sylvain Wallez wrote:
>>
>>> BTW, why do you prefer v2 rather than v1?
>>
>> <..schnip!..>
>
>
> One thing I don't care so much for in v2 is the idiom of attaching 
> view data as properties of the widget tree root.  The minimalist 
> approach (losing 'bizData') was clever, but in actual practice I find 
> that I really like having one locus of transfer of data between the 
> flowscript and the presentation, so I usually end up with something 
> like this anyway:
>
>     w.viewData =
>         {
>             schtuff:     foobar,
>             etc:        otherStuff
>         };
>     form.showForm ('whatev');


Uh? Didn't knew about that, and looks hacky IMO.

> ...and so I guess I'd rather have it as an explicit parameter (and 
> also not needing to have 'viewData.' at the head of the expression 
> path within the JX template).
>
> While on the subject... since I am "Mr. Anal Nomenclature Pants", I 
> would vote for changing 'bizData' to 'viewData' (as in v3)... a much 
> better name IMHO :-)


And I *totally* agree with you, as this data is exclusively prepared for 
and consumed by the view!

Sylvain

-- 
Sylvain Wallez                        Anyware Technologies
http://apache.org/~sylvain            http://anyware-tech.com
Apache Software Foundation Member     Research & Technology Director


Re: v2 (was Re: [CForms binding] access to model data from repeater row widget)

Posted by Mark Lundquist <ml...@wrinkledog.com>.
On Jun 21, 2005, at 8:41 AM, Mark Lundquist wrote:

>
> On Jun 20, 2005, at 11:42 PM, Sylvain Wallez wrote:
>
>> BTW, why do you prefer v2 rather than v1?
> <..schnip!..>

One thing I don't care so much for in v2 is the idiom of attaching view 
data as properties of the widget tree root.  The minimalist approach 
(losing 'bizData') was clever, but in actual practice I find that I 
really like having one locus of transfer of data between the flowscript 
and the presentation, so I usually end up with something like this 
anyway:

	w.viewData =
		{
			schtuff:	 foobar,
			etc:		otherStuff
		};
	form.showForm ('whatev');

...and so I guess I'd rather have it as an explicit parameter (and also 
not needing to have 'viewData.' at the head of the expression path 
within the JX template).

While on the subject... since I am "Mr. Anal Nomenclature Pants", I 
would vote for changing 'bizData' to 'viewData' (as in v3)... a much 
better name IMHO :-)

cheers,
—ml—


v2 (was Re: [CForms binding] access to model data from repeater row widget)

Posted by Mark Lundquist <ml...@wrinkledog.com>.
On Jun 20, 2005, at 11:42 PM, Sylvain Wallez wrote:

> BTW, why do you prefer v2 rather than v1?

Honestly I can't remember ATM... :-)

I switched a long time ago because (a) I was under the impression that 
v2 was where the form API was headed, and (b) more importantly, there 
were specific things that I could do in v2 and not in v1.  I think the 
the clincher had to do with actions, and being able to access something 
or other from within the action callback, or something.  Like I said, I 
switched long enough ago that I can't remember now in terms of "can't 
do that in v1" things.

I'm actually using a custom extension to Form that encapsulates a 
standard usage model that I've settled on, mostly naming and locations 
of things.  And I based that on v2, so for the time being I've stuck 
myself with it :-)

—ml—


Re: [CForms binding] access to model data from repeater row widget

Posted by Sylvain Wallez <sy...@apache.org>.
Mark Lundquist wrote:

> Hi,
>
> Here is a scenario that I keep finding myself dealing with...
>
> Some repeater is bound to a collection, and also contains one or more 
> widgets that are /not/ bound to the collection elements. For instance, 
> there might be a checkbox that means "do something to/with the thing 
> in this row". After accepting the form, the processing entails 
> iterating through the rows and doing something something with the 
> corresponding object from the model layer, which means I need to be 
> able to find/access that object.


So in essence, you want to act on the selected rows, right? I 
encountered this already, and I've been thinking to explicitely add the 
selection concept to repeaters. That selection would be defined by a 
boolean field present on each row. Note that a boolean field doesn't 
necessarily means rendering as a checkbox. It can also be some 
highlighting of selected rows.

That would lead to
<fd:repeater name="repeater" selection="select">
  <fd:widgets>
    <fd:field id="name"/>
    <fd:booleanfield id="select"/>
  </fd:widgets>
</fd:repeater>

Repeater actions such as "delete-rows" would then no more have a need to 
be given the select widget's name as of today.

And even more, repeater actions could have constraints on the selection 
size, such as single-selection, multiple-selection, leading these 
actions to be disabled if their associated constraint isn't met.

And finally, we may be able to specify on repeater bindings if they have 
to act on the whole repeater on just on the selection.

> It seems like each time, I come up with some different way of handling 
> this, and none of them ever feels quite right.
>
> Then I thought, if the binding framework would decorate each repeater 
> row widget with a property that references the bound object, things 
> would just be a lot cleaner.
>
> So I made this trivial change, and it works great. The repeater rows 
> now have a "model" property that references the model object to which 
> that row is bound. I tweaked the JXTG macro version of the template 
> engine so that I can reference "${model_}" from within the 
> <ft:repeater-widget>. That is really handy, because it lets me avoid 
> having to specify a bunch of output widgets in the the form definition 
> + binding. What I really had in mind with this change, though, was 
> making the flowscript easier, and it does do that... but currently in 
> the flow I have to unwrap() the repeater row widget by hand before I 
> can call getModel() on it, so before I finalize this I want to add 
> that to the Form flow API. Then I think it will be just right.
>
> However...
>
> I realized that I have a nomenclature clash with my choice of the name 
> "model". I've been using the v2 API for a long time, so I forgot in 
> v1, there is a Form.model property that denotes the widget value tree.


The "model" property is only available on the toplevel form JS object, 
so there may not be a clash. BTW, why do you prefer v2 rather than v1?

> So I don't want to cause confusion with another sense of "model"... it 
> should be called something else. "rowData"? "rowObject"? WDYT?


It doesn't seem good to me to provide at the API level a way to link the 
form to the data model, as this is something that isn't suitable for all 
situations (think transactional systems, heavyweight objects, etc). And 
one of the big strengths of CForms is its strong isolation with the data 
model while the user is messing around with input values.

However, there are some uses cases where this makes sense. You can then 
use widget attributes (see get/setAttribute) to attach some application 
data of your liking to any widget, including repeater rows.

You can also have a look at the new Tree widget in trunk. It relies on a 
lightweight model to access arbitrarily large hierarchies. And a 
repeater is not far from being a tree of depth 1 :-)

Sylvain

-- 
Sylvain Wallez                        Anyware Technologies
http://apache.org/~sylvain            http://anyware-tech.com
Apache Software Foundation Member     Research & Technology Director


Re: [CForms binding] access to model data from repeater row widget

Posted by Reinhard Poetz <re...@apache.org>.
Mark Lundquist wrote:
> Hi,
> 
> Here is a scenario that I keep finding myself dealing with...
> 
> Some repeater is bound to a collection, and also contains one or more 
> widgets that are /not/ bound to the collection elements. For instance, 
> there might be a checkbox that means "do something to/with the thing in 
> this row". After accepting the form, the processing entails iterating 
> through the rows and doing something something with the corresponding 
> object from the model layer, which means I need to be able to 
> find/access that object.
> 
> It seems like each time, I come up with some different way of handling 
> this, and none of them ever feels quite right.
> 
> Then I thought, if the binding framework would decorate each repeater 
> row widget with a property that references the bound object, things 
> would just be a lot cleaner.
> 
> So I made this trivial change, and it works great. The repeater rows now 
> have a "model" property that references the model object to which that 
> row is bound. I tweaked the JXTG macro version of the template engine so 
> that I can reference "${model_}" from within the <ft:repeater-widget>. 
> That is really handy, because it lets me avoid having to specify a bunch 
> of output widgets in the the form definition + binding. What I really 
> had in mind with this change, though, was making the flowscript easier, 
> and it does do that... but currently in the flow I have to unwrap() the 
> repeater row widget by hand before I can call getModel() on it, so 
> before I finalize this I want to add that to the Form flow API. Then I 
> think it will be just right.
> 
> However...
> 
> I realized that I have a nomenclature clash with my choice of the name 
> "model". I've been using the v2 API for a long time, so I forgot in v1, 
> there is a Form.model property that denotes the widget value tree. So I 
> don't want to cause confusion with another sense of "model"... it should 
> be called something else. "rowData"? "rowObject"? WDYT?
> 
> please advise! :-)

no advice but a link: see 
http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=109950611823830&w=2


-- 
Reinhard Pötz           Independent Consultant, Trainer & (IT)-Coach 

{Software Engineering, Open Source, Web Applications, Apache Cocoon}

                                        web(log): http://www.poetz.cc
--------------------------------------------------------------------