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