W3C home > Mailing lists > Public > www-forms@w3.org > August 2004

RE: complex mutually exclusive selections

From: Mark Birbeck <mark.birbeck@x-port.net>
Date: Wed, 18 Aug 2004 21:35:51 +0100
To: "'Andrew MacDonald'" <andrew_james_macdonald@yahoo.com>
Cc: <www-forms@w3.org>
Message-ID: <001201c48562$f4a7e6b0$0a01a8c0@W100>

Andrew,

> Is there a way in XForms to produce the equivalent to 
> the following HTML? [snip] I tried to do something similar
> in XForms, but  discovered that placing input elements within
> item elements isn't allowed.Is there an alternate way to do 
> this?

As it happens, HTML doesn't actually support what you want. First, you can't
nest <input> controls - in HTML there is no closing tag for <input>, and in
XHTML <input> is defined as being empty. Also, the behaviour of radio
buttons is only in relation to the submission of data, not to interaction
with other controls, so even if you 'un-nest' the controls, the relationship
between them (that one control is used to indicate a choice amongst one or
other controls) would have to be defined with script.

The good news is though, that XForms *does* support this - these are exactly
the types of scenarios that the language set out to solve without using
spaghetti script. And there are actually a number of ways to do what you
want, depending on whether you are simply manipulating the user interface,
or whether you are making decisions in the flow of form-filling based on
other data in the form.

The technique that is usually the easiest to understand is the use of switch
and case. Here only one section of the form - from amongst a number of
mutually exclusive alternatives - is 'active' at any time. Exactly which
section is active is dictated by the use of a toggle instruction.

An illustration of using this is given here:

  <http://www.formsplayer.com/demo/switch-case/print-settings.html>

It's aimed at formsPlayer, but should work in other XForms processors. You
can read the source if you don't want to install anything.

One of the disadvantages of this technique though, is that you have to
mark-up the conditions under which your toggles will be used to select from
amongst the sections. And it gets even more complicated if you actually want
a number of 'active' sections, based on information that your user has
already provided.

A much more powerful technique is to use what we call 'model-based
switching' - essentially leaving the activation and de-activation of your
controls to the XForms processor, based on conditions that you specify. This
is achieved with the 'relevant' model-item property (MIP). In effect you are
saying that some node is 'active' if some condition is met, and is not
active otherwise. Any controls that are bound to that node will
automatically get notified by the processor, as the node changes state.

An example of this is given in the XForms test suite:

  <http://www.w3.org/MarkUp/Forms/Test/chapter6/relevant.xml>

If you are running formsPlayer then a converted version of the form with the
<object> tags in, is available here:

  <http://www.formsplayer.com/TestSuite/chapter6/relevant.html>

As you can see, a node 'health' in the instance data is 'relevant' only if
some other node (called 'is-senior') is set to true:

  <bind
   nodeset="health"
   relevant="boolean-from-string(../is-senior) = true()"
  />

With this single statement *any* control that uses 'health' will have its
CSS state automatically set by the processor, based on the calculation. In
the form we're looking at here, it's actually a <group> that relies on the
data:

  <group ref="health">
    <label>Health Matters</label>

    <input ref="heart">
      <label>Heart Condition</label>
    </input>

    <range ref="bp/diastolic" start="0" end="300">
      <label>Diastolic Blood Pressure</label>
    </range>

    <range ref="bp/systolic" start="0" end="300">
      <label>Systolic Blood Pressure</label>
    </range>
  </group>

So, to complete the picture, all that is needed is a CSS rule that hides the
display of any control that is bound to a node that is 'not relevant'. This
is defined as follows:

  *::disabled { display: none; }

(If you are using formsPlayer then use .disabled instead of ::disabled.)

Now this entire group of controls will become hidden if the user fills in a
control that indicates they are not a senior citizen (and reappear again if
the form filler ages quickly).

Note that this same technique can be used to build a wizard-style form in a
just a few lines of mark-up:

  <http://www.formsplayer.com/demo/wizard/model-based-switching.htm>

Note that normally quite complex constructs such as "don't show the [NEXT]
or [PREV] button if we are at the end or beginning of the list" are easily
constructed using the above technique on <trigger>s.

Regards,

Mark


Mark Birbeck
CEO
x-port.net Ltd.

e: Mark.Birbeck@x-port.net
t: +44 (0) 20 7689 9232
w: http://www.formsPlayer.com/

Download our XForms processor from
http://www.formsPlayer.com/
Received on Wednesday, 18 August 2004 20:36:01 GMT

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