cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sylvain Wallez <>
Subject Re: CForms Binding - Cross Referenced Data (duplicate of post on users)
Date Mon, 14 Mar 2005 10:14:13 GMT
Ben Pope wrote:

>First of, sorry for the post here, but I've asked a few times on users and
>not had this solved, so I'm gonna cross my fingers and post here:
>This is something I've been struggling with, on and off, for some time now.
>Assume I have some data as follows:
>   <people>
>      <person id="0">
>         <name>Me</name>
>      </person>
>      <person id="1">
>         <name>You</name>
>      </person>
>      <person id="2">
>         <name>Him</name>
>      </person>
>   </people>
>   <rooms>
>      <room id="0">
>         <name>Lounge</name>
>         <person idref="0"/>
>         <person idref="1"/>
>      </room>
>      <room id="1">
>         <name>Kitchen</name>
>         <person idref="2"/>
>      </room>
>   </rooms>
>That describes a list of people which are in a particular room, so Me and
>You are in the Lounge and Him is in the Kitchen.
>I want to have a form that displays, for a given room, a list of the people
>in it.
>A repeater is obviously the first choice, but there are a few
>counter-intuitive thingsd going on:
>I need to be able to modify the name of the person.  Simply running the
>repeater over the rooms is not enough.
>Adding a row needs to add an rooms/room/person with an idref - I'll then use
>client side javascript and XMLHTTP to allow the user to select a person (by
>id) to fit in the space, as all the people are predefined.  I do not want to
>have the repeater add /people/persons.
>I've toyed with a few ideas:
>id is passed in as a parameter, and this code is actually in a stylesheet -
>but ignore that for now.
><fb:repeater id="people" parent-path="/project/rooms/room[@id={$id}]"
>This "solution" has the result of being perfect for load.  However, when I
>save it, it breaks, because I can't have an xpath predicate.  So what do I
>set the row-path-insert to?
>If I set row-path-insert="/project/people/person" and bind the id (which is
>fb:identity) in both directions, /project/people/ ends up correct, but
>/project/rooms/room/ doesn't get updated.
>I've tried
>      <fb:on-insert-row>
>         <fb:context path="/project/rooms/room[@id='0']">
>            <fb:insert-node>   <person idref="5"/>
>      </fb:insert-node>
>But then I get a new node in both /rooms/room[@id='0']/ which is correct,
>and another node created in /project/people/ which is the usual binding for
>person and is a copy of the existing one.  This doesn't seem correct to me.
>Hmm, I've had a little play with fb:javascript but I don't know what I'm
>doing... Ideally I would remove all the /rooms/room[@id='x']/person fields
>and repopulate with the list of ids in the repeater.  I can't seem to work
>out the correct APIs, it always says that such and such method doesn't exist
>- can anybody point me in the right direction?
>I've toyed with the idea of having two repeaters, and updating one from the
>other but it sounds like a recipe for disaster.
>Another idea was to have a play around with it in flow, but I suspect I'd
>end up with exactly the same problems I have using fb:javascript, with the
>disadvantage of distributing the binding code.
>Any help is much appreciated, I'm confused by the number of options and
>multitude of interfaces.
>I can't be the only person working with cross-referenced data!  I'm either
>missing something or the repeater just doesn't understand this construct - I
>wonder if Sylvain has any ideas on this.

Hmm... I hope I'm not the only one to do fancy CForms stuff :-/

Your room repeater links to existing people through their ID but should 
display their name. This is typically a selection-list with IDs as 
labels and names as values.

About the ability to add new names at any level, this looks like a 
combo-box (editable dropdown). We've hacked such a thing for one of our 
projects, and basically the idea is to have a single widget be rendered 
as two inputs.

Say you have
<fd:field id="personref">
  <fd:selection-list src="cocoon:/person-selection-list"/>

The editable combobox renders this as :
- a dropdown list of name "personref" with the contents of the 
- an input of name "personref.label".

When the user chooses in the dropdown, the selected value is copied to 

When the user types in the personref.label input, a new option is added 
to the dropdown, having "new" as a value, and the typed text as label.

On form submit, the flowscript checks if "personref" equals "new" and if 
true creates a new person with the name in the "personref.label" request 
parameter and replaces the "new" value with the newly created id.

Binding can then go on as usual.

This is a bit hacky, but it works :-)

Hope this helps,

Sylvain Wallez                                  Anyware Technologies 
{ XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects }

View raw message