Forum OpenACS Q&A: break out of a multiple tag?

Collapse
Posted by tammy m on
Hi,

I want to do the equivalent of

<multiple name=elements>
    <if @elements.id@ eq height_in>
      <break>
    </if>
     .... more processing

Is there any way to break out of looping through a multiple adp tag?

thanks:)

Collapse
Posted by Tilmann Singer on
If the multirow is created from a db call directly then you can do it like this:

db_multirow elements elements { } {
  if bla {
    break
  }
}

If you create it manually do the analogue to this in your code.

Follows the good principle of not putting unnecessarily logic into the adp file.

Collapse
Posted by Tom Jackson on

Of course if you have two templates for one multirow datasource, the condition to 'break' or 'continue' could be different. It should be possible for the designer to decide what rows, or what part of a multiple tag gets processed. I don't think this is currently possible. It sure would be nice.

Collapse
Posted by Tilmann Singer on
Well you could if you really need it make the unwanted elements invisble like this:

<multirow>
<if not @multirow.some_value@ gt @my_limit@>
...
</if>
</multirow>

Would result in a few unnecessary loop runs, but it is available right now.

Simplicity is a great feature of the templating language - it's designed to be easy to explain to non-programming graphic designers. I am not sure if I want to explain the concept of break and continue to them, but then if it's clearly marked as advanced feature in the documentation, why not.

Collapse
Posted by tammy m on
Hmm,

Well actually what I'm doing is surely considered a major hack approach but I'm trying to get something done relatively quickly and painlessly here (getting some functionality up is more important now than elegance or generic reuse)...

What I am doing is creating a custom form resource/style (replacing standard-lars) that is paired with a specific form to handle pairing certain widgets into single table rows, etc.

I know I could do this with an adp using the formwidget/formerror/etc tags but then I would have to write a lot of html table code and include every formwidget and it would be long and tedious. But the generic form style is not gonna work either since it lays all widgets out one per table row. I need several to be paired in a single table row in some cases etc.

Maybe the correct way to be doing this is using something I ran across in the Templating System docs:

Starting with an autogenerated form template

In most cases, the simplest way for the designer to get started is to edit the autogenerated form template. This template will have all the necessary formwidget and formgroup tags.

But how do I get my autogenerated form template with the formwidget tags in it?!

Of course my form adp will still be long and any added widgets will need to be added by hand (the tcl and adp kept in sync) versus picked up in the style multiple name=elements loop for free.

It's frustrating how very close the standard form style comes to a perfect form rendering for almost no effort (formtemplate tag only). Then for just a tiny bit of customization from that for a single form, I have to write a load of formwidget | formerror | formgroup tags and my own HTML structure. Sigh. If only I had time/knowledge right now to add

  1. more flexible form sections -- template::element::create accepts a section and if not defined yet, defines it. Any elements later added via template::element::create can be added to existing or new sections.
  2. associating widgets so that when "linked" to each other, the standard template displays them in the same row, separated by their labels (if they have them).
  3. This would rock! Then I'd be able to just use a single formtemplate tag for all my forms, even the huge ones generated from CR content_types:)

    Alas I am a newbie and am struggling to implement a site with specific functionality in a decent time frame to prove we can use ACS for our purposes. So hacking a form style template seems the way to go now!

    Which brings me back to: should I continue to hack the custom-per-form style templates (only for really large, CR-generated forms that have to be "per designer's specs" visually) or figure out how to get my autogenerated template containing the formwidget etc tags and hand tweak that?

    sorry for the verbosity and tia:)

    btw, I still think it'd be mighty handy to be able to break or continue from within a multiple tag;(

Collapse
Posted by Don Baccus on
Adding a "break" command would encourage poor programming style - you *always* want to write your queries to return the exact number of rows you're going to display, otherwise the RDBMS is being asked to do unneeded work.  And that unneeded work chews up server resources.  Given that the RDBMS tends to be the bottleneck which controls how many pages per second you can serve on a site ... asking it to do unneeded work is in general a really bad idea.

Since doing a "break" should be a very rare thing ... is it really an issue that you must do it at the Tcl level rather than ADP level?  This isn't really something you want in a template used by many scripts IMO for the reason I mention above ... you're implying that you're going to write queries that ask the RDBMS do more work than necessary.

As far as your templating question goes ... it would be nice to extend things so it's easier to put multiple form elements on one row.  I haven't played with grouping to try to do this but I've had the same annoyance.  Using a form style is so simple that having to drop back to hand-writing formtemplate code is a real drag.

Collapse
Posted by tammy m on
Hi Don,

As you say you *always* want to write your queries to return the exact number of rows you're going to display, I totally agree.

But (knew this was coming!) in my case, I have selected just what I need out of the database and am only wanting to break or continue so that I can pair certain of these selected widgets together in my resulting HTML table. Not because I don't want them at all! If I could break or continue in my form style, I could have a special case for just a few widgets , thus pairing them in a table row. So there are gonna be special cases where it's not bad programming (and most languages have these commands). And regardless of language enforcements, etc, programmers will always come up with ways to do the wrong thing!

Anyway that aside, I can do what Tilmann suggested with the enclosing if to accomplish the effect I'm after. But it is much harder to see the logic this way. You have to find the end of the if which is just not visibly available, since the file is long. Easy to work around yes but just not as clear to anyone reading the code, IMO. But not to start a flame about minor issues, I'm quite happy with my end result:)

thanks again everyone

Collapse
Posted by Tilmann Singer on
Tammy, are you sure you can't achieve what you want using the <group> tag? If there is a common attribute that is the same for those elements that you want to display in the same table row it should be possible, no?

Unfortunatly 'sections' don't add that attribute value to each element but rather insert their own separator element as far as I remember. But maybe you can add your own or add some semantics to the element id.

Collapse
Posted by tammy m on
Hey,

You may be on to something with the <group> tag! I can't find any attributes my form elements that I want to group share though. Is there a way I can add an attribute to my form elements? Then I could use <group> like is done for the section element in form styles.

Functionally, the 'sections' do put a separator in but the code to do it in the adp looks like <group column="section"> so I think it does this by adding an attribute to each element in a 'section.'

Collapse
Posted by Jeff Davis on
Here is a code snippet from acs-templating/resources/forms/standard.adp with a break. It's ugly and bad practice, but it does work (and I think might point to some places where it might make some sense to have a break tag).
<multiple name="elements">
  <if @form_properties.show_required_p@ true>
    <if @elements.optional@ nil and @elements.mode@ ne "display" and @elements.widget@ ne "inform" and @elements.widget@ ne "select" and @elements.widget@ ne "h
idden" and @elements.widget@ ne "submit">
       <span class="form-required-mark">*</span> #acs-templating.required# 
       <% break %>
    </if>
  </if>
</multiple>
Collapse
Posted by tammy m on
Wow,

Thanks Jeff:) How did I miss that?! I have been looking at form style standards all day. Bad eyes? Not to mention that, looking at the sample you posted, it seems so obvious now. Sigh. Programming is sometimes not so easy on the ego!

Collapse
Posted by Don Baccus on
I don't consider this a solution and am sorry to see it in our code.  It assumes knowledge of the implementation of the "multiple" and any tag included within it, knowledge that shouldn't be in an .adp file.

If we're going to stoop to code like this then I suppose we should provide a break tag ...

Collapse
Posted by Don Baccus on
For standard.adp wouldn't it be a tad bit cleaner  to have the form builder track if a form has any required fields and have standard.adp query that state variable rather than pull a kludge like this?  More efficient, too ...
Collapse
Posted by tammy m on
Yeah yer right.

The "multiple" and "group" tags both add a "loop" layer and it gets real easy to hurt yourself assuming knowledge of implementation of tags. Especially given that should be able to change without affecting your adp;(

Collapse
Posted by Tom Jackson on

I agree that the mixing of tcl code and templating tags to get something to work is a real abuse of the templating system. I can't think of a great reason to be using 'break' after considering Don's comments that the database/tcl code should be doing this job.

The code snip provided above seems to be using some obfuscated logic to put one element on the page. I think an extra bit of tcl code, or even a database query would be a cleaner way of getting what you want, and documenting what it is you are trying to do.

But maybe there are good reasons to use 'break'. What are they? Is 'continue' in the same boat? When would it be useful? What are the benefits over using 'if'?

Collapse
Posted by Don Baccus on
The snippet from the standard form template is running through the elements a second time (after they've been rendered) to see if a "* means required" line should be put out - i.e. if there are any required input fields.

The code only wants to put out one such line thus the Tcl "break" call.

Just to clarify what it's doing ...

Collapse
Posted by tammy m on
Well,

I can share why I would like to use continue in my code (copied from above in this thread).

But (knew this was coming!) in my case, I have selected just what I need out of the database and am only wanting to break or continue so that I can pair certain of these selected widgets together in my resulting HTML table. Not because I don't want them at all! If I could break or continue in my form style, I could have a special case for just a few widgets , thus pairing them in a table row.

Anyway that aside, I can do what Tilmann suggested with the enclosing if to accomplish the effect I'm after. But it is much harder to see the logic this way. You have to find the end of the if which is just not visibly available, since the file is long. Easy to work around yes but just not as clear to anyone reading the code, IMO. But not to start a flame about minor issues, I'm quite happy with my end result:)

And actually, it turned out harder to debug too as the many if ... else's in my adp weren't paired up how I intended at first. It is just more clear to my eye to have a clear if... continue at the top of a loop instead of a not so immediately visible long if ... else (itself containing lots of if ... else conditions). Just my current situation;)

Collapse
Posted by Dave Bauer on
So what we _really_ need is a way to group form elements. I worked on a site that needed this also. They ended up using the form templating commands in each ADP to arrange the elements the way the designer wanted to.

I think a simple way to group elements would be generally useful. The way grouped elements are presented could be determined by the form template.

One use, first_names, middle_initial, last_name on one line.

Another use is when extending a form. I might want to add an element in the middle of a form to keep related elements together when dynamically building a form.

Collapse
Posted by Don Baccus on
Yes, some form of element grouping would be useful if it were simple and easy to understand.