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
--------------------------------------------------------------------