W3C home > Mailing lists > Public > www-forms@w3.org > November 2006

Re: repeats

From: John Boyer <boyerj@ca.ibm.com>
Date: Sat, 4 Nov 2006 12:05:18 -0800
To: jeacott@hardlight.com.au
Cc: www-forms <www-forms@w3.org>
Message-ID: <OF5794F227.6F634901-ON8825721C.0068B586-8825721C.006E5AB4@ca.ibm.com>
Hi Jason,

Thanks for starting the sample.  You have two distinct data sets.  Did you 
mean that either could be used as the prototype for the *same* repeat or 
two different repeats?  If two different repeats, then I still don't see 
how you're generating a problem.  If the same repeat, then I still don't 
see why it isn't the same and likely *worse* to take a snapshot of data on 
startup to use for insertions.

Regarding the statement that 1.1 fixes repeats, but they're only toys in 
1.0, I am responding that in *1.0* I can construct repeats to arbitrary 
depth, they can become empty, and they can become non-empty again through 
an insertion *even at arbitrary depth*.  I can make the repeat enforce a 
minimum of one row as a rule, so that if you delete the last row, it 
simply empties itself, and I can do so with a single action (i.e. the 
action sequence does not need to be tailored to the data schema). 

Remember that link I sent in prior email?  It contains a description of 
the things you can do to achieve this.  Here it is again: 
http://www.idealliance.org/proceedings/xml05/ship/74/XFormsAndXFDL_Boyer.HTML#d0e1785

To follow my own request, here is an example.  Suppose you want a repeat 
that starts empty (like an empty shopping cart):

<!-- Initial instance data contains the prototypical node as the last 
element -->

<xf:instance xmlns="">
   <cart>
      <item>
          <name/>
          ...
   <cart>
</xf:instance>
...

<!-- repeat omits the prototypical node -->

<xf:repeat nodeset="item[position()!=last()]" id="repeat-cart">
   ...
</xf:repeat>

<!-- Add new row after any current row, but do it in a way that can
     also handle zero rows. -->

<xf:trigger>
   <xf:label>Insert</xf:label>
   <xf:insert ev:event="DOMActivate" nodeset="item" 
at="index('repeat-cart')+1" position="before"/>
</xf:trigger>

<!-- Delete a row from the repeat. If only the prototypical data remains
     then the nodeset becomes empty and the action has no effect. -->

<xf:trigger>
   <xf:label>Delete</xf:label>
   <xf:delete ev:event="DOMActivate" nodeset="item[position()!=last()]" 
at="index('repeat-cart')"/>
</xf:trigger>

Finally, because it seems to be such a sticking point, let me show you 
what can be done in XForms 1.0 if *insert* also has no effect on empty 
nodeset.  The prior argument that we don't know where to insert should be 
good enough, and consistency with the no-effect behavior of delete (the 
utility of which is shown above) should also be good enough, but it turns 
out that we actually *need* this aspect of insert to drive another use 
case for repeats.  Suppose that instead of a zero row repeat, you want a 
repeat that stays at one row.  If the user hits delete for that row, then 
the row stays, but the data is cleared from it.  Further suppose that you 
want a general method, and not something that requires you to write a 
bunch of setvalue actions tailored to the data (which doesn't work in the 
nested repeat case anyway).  In other words, suppose you want to be able 
to accomplish this feat with a *constant* number of actions regardless of 
the shape of the data:

<xf:trigger>
   <xf:label>Delete</xf:label>
   <xf:action ev:event="DOMActivate">
      <xf:delete nodeset="item[position()!=last()]" 
at="index('repeat-cart')"/>
      <xf:insert nodeset="item[last()=1]" at="1" position="before"/>
   </xf:action>
</xf:trigger>

The delete action only deletes the last row of data that the repeat is 
actually showing.  The insert follows that up with a nodeset that resolves 
to empty unless the only data left is the prototypical data.  If there is 
anything more, the insert has no effect.  But when only the prototype is 
left over, we make a new copy of it, which presents a single empty row of 
data to the user.

The neat thing is that this method works even if the repeat contains 
repeats.  The last row we are deleting may contain repeats with multiple 
rows.  Those are deleted and then the insert puts in new prototypical data 
in which the inner repeats only have one row.  No 'if', no 'while', no 
actions that have to know the structure of the data.  Just two actions. 
Just XForms 1.0.

John M. Boyer, Ph.D.
STSM: Workplace Forms Architect and Researcher
Co-Chair, W3C Forms Working Group
Workplace, Portal and Collaboration Software
IBM Victoria Software Lab
E-Mail: boyerj@ca.ibm.com  http://www.ibm.com/software/

Blog: http://www.ibm.com/developerworks/blogs/page/JohnBoyer





Jason <jeacott@hardlight.com.au> 
11/04/2006 02:03 AM
Please respond to
jeacott@hardlight.com.au


To
John Boyer/CanWest/IBM@IBMCA
cc
www-forms <www-forms@w3.org>
Subject
Re: repeats








John Boyer wrote:
> 
> Hi Jason,
> 
> Sorry, but the stuff you are writing is really hard to respond to.  It's 

> just a stream of thoughts that makes huge assumptions every few 
> sentences that I understand certain things you haven't said.

sorry.

> For example, you say that great care would needed to be taken when 
> dealing with newly loaded data sets that might be subtly different than 
> prior ones in the form.  It escapes me how this point manages to 
> substantiate the complaint about the processor not taking a snapshot of 
> instance data on initialization. In fact, you are exactly describing 
> one of the things that was broken about the old method. 

this is just because suddenly you need 2 matching instances. 1 acting as 
prototype, and 1 containing working data. This was never a problem 
previously because it wasn't possible. My issue here is that in many 
cases the new regime is not required, so why not allow both options to 
coexist. that way simple forms stay really simple.
if for example you had 2 distinct sets of data like this
set 1
-----------
<data>
                 <somenodeA/>
                 <somenodeB someatt="true"/>
</data>
-----------
set 2
-----------
<data>
                 <somenodeA/>
                 <somenodeB/>
</data>
-----------

these could both conceivably be managed by the same xform, including 
repeats. but in the new 1.1 scenario I'll need 2 distinct prototype 
instances.
this is a simple fictitious example but there could easily be real 
reasons for doing this sort of thing. So when I load set1 I'd really 
need to be loading its matching prototype too, and then saving them 
together etc, and inventing ways to ensure they were matching pairs. 
Thats why I suggested that it might be difficult to manage. And as I 
said, I havent thought about it much, it was just something I thought 
could cause problems.

> In XForms 1.0, the <instance> element contains or references the initial 

> instance data, and the snapshot was taken during model-construct.  If an 

> instance replacement submission brought in new data over which a 
> repeat/insert should operate, but there was no matching data in the 
> initial instance data, then insert would just fail.

thats true.

> This conversation would therefore really benefit from some exact use 
> cases with example markup because your claim that XForms repeats are now 

> just for toy forms is not just hyperbole, it's just plain wrong.

I claimed this for 1.0 - I acknowledged that its fixed with 1.1

> The new design even of XForms 1.0 allows one to actually create 
arbitrarily 
> deeply nested repeats, not just one level, and it allows one to do so in 

> a way that survives a save/reload (e.g. submit data to server and come 
> back tomorrow to finish purchase order).

I'm not sure how this works - maybe I'm reading the wrong docs.
xforms 1.0?
http://www.w3.org/TR/2006/REC-xforms-20060314/slice9.html#action-insert

only has 'position' & 'at'
so if our user removes all her items from the shopping list - how do you 
start over? This is where my issue lies, so now all the forms I have 
that use this scenario (pretty much all of them) are broken and cannot 
be repaired as far as I can tell with 1.0 alone. If you have a way I'd 
dearly love to hear it.

I could always create nested repeats without problem. I think I tried to 
indicate that I still dont think its possible to produce arbitrarily 
deep on-the-fly child nodes and track them automagically with the view 
to create dynamic trees. I also dont think its possible to create one 
view that can display arbitrary data without that view requiring 
modification each time.

> And I still don't understand why you believe that insert on empty 
> nodeset should do something.  Even if you did have a prototype available 

> (i.e. pretend the above language faults did not exist), when the nodeset 

> resolves to empty, where should the node be inserted?

The processor knows where to look to determine that the nodesetcount is 
zero, so wouldn't it add the insert where it finds the zero count? or 
where a bind states it should be? If that parent is also missing THEN 
you could reasonably decide to do nothing. This seems like sensible and 
predictable behaviour - you could even put a switch on the insert to 
allow chasing back to the first recognisable ancestor, even if its the 
root node and then rebuild the node to be inserted and all the 
intervening ones. I dont know if that would be useful or not, but I dont 
see that its not possible.

In the interests of keeping this short - I accept your points re switch 
etc - I was just suggesting some things that I found awkward that seem 
only to make creating forms more cumbersome I wasn't suggesting any 
priorities at all.

I do truly appreciate your efforts, especially in responding to my 
previous stream of consciousness response.

Cheers
Jason.
Received on Saturday, 4 November 2006 23:46:20 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Saturday, 10 March 2012 06:22:07 GMT