lost password?

home
•  xaraya +
•  rails
•  django
•  webdev
•  xamp
•  musings

rss
Tag this page
   

ยป Blogs that link here
last modified: Dec 06, 2006
(first posted: Dec 06, 2006)
(1887 Reads)
keywords: images pageform uploads
Permalink

Handling Plain Upload Fields in a Pageform

Xaraya's Dynamic Uploads Property is very flexible allowing multiple methods of attaching files. But in most cases, I just want a file input field (text box plus browse button), and don't want to require users to make the extra click to reveal the uploads box. And then it gets a bit tricky when you allow users to hit the back button, and re-submit with or without specifying a new file name.

Just an Upload, Please

First, I often just want to use an "Upload" attach method only, not all the other methods (like Trusted, External, Stored). That's usually all that is needed in a typical web app.

To make it from the Uploads property however, you need to dissect the property template. Unfortunately we can't override property templates for single instances, just theme-wide. (Also it uses the "dd_" prefix, I know you can override that with your own name but don't know how to that here). The changes need to be made in the object-specific showform template.

If the showform template normally would contain for the full blown uploads property:

<xar:data-input property="$properties['img']" />

It could be replaced with:

<xar:set name="prop">$properties['img']</xar:set>
<xar:set name="propid">"dd_" . $prop->id . "_attach_upload"</xar:set>
<xar:set name="typeid">"dd_" . $prop->id . "_attach_type"</xar:set>
<label for="$propid" class="xar-form-label">Attach Image File: </label>
<input type="file" name="$propid" id="$propid" />
<input type="hidden" name="MAX_FILE_SIZE" value="10000000" />
<input type="hidden" name="#$typeid#" id="#$typeid#" value="1" />
<xar:set name="invalid">$properties['img']->invalid</xar:set>
<xar:if condition="!empty($invalid)">
<span class="xar-error">#$invalid#</span>
</xar:if>

I've gotten this to work without including the attach_type input field. But it's definately needed in the next case.

Let 'em Back / Re-submit, please

Next problem, let's say you've submitted the form, and hit the back button. If you browse or enter a new file name to upload, and submit it, the new file gets uploaded and replaces the previous one.

But if you leave the upload field blank and hit submit, you would expect it to revert to the previous one. In fact, a blank value is passed, wiping out the previous one.

How does the xar:data-input tag for the property do it? It creates a hidden "Stored" method (7) input tag with value of the previous uploaded file selected. This is generated even if you've disabled the Stored method in the property's validation. The resulting code is something like this:

<div id="dd_170_attach_stored" style="display: none;">
<select name="dd_170_attach_stored[]" id="dd_170_attach_stored_id" size="5">
<option value="642" selected="selected">imports/100_3688.JPG</option>
</select>
</div>
<input type="hidden" name="dd_170_attach_type" id="dd_170_attach_type" value="7" /

Then, when a user specifies a file to upload, javascript changes the attach_type value from 7 to 1, and a new value is submitted in the attach_upload (<input type="file") tag.

We can do something similar in our dissected snippet.

<xar:set name="prop">$properties['img']</xar:set>
<xar:set name="stored">"dd_" . $prop->id . "_attach_stored"</xar:set>
<xar:set name="storedid">"dd_" . $prop->id . "_attach_stored_id"</xar:set>
<input type="hidden" name="#$stored#[]" id="#$storedid#" value="#$img_output['fileId']#" />

<xar:set name="propid">"dd_" . $prop->id . "_attach_upload"</xar:set>
<xar:set name="typeid">"dd_" . $prop->id . "_attach_type"</xar:set>
<label for="$propid" class="xar-form-label">Attach Image File: </label>
<input type="file" name="#$propid#" id="#$propid#" onchange="javascript:document.getElementById('#$typeid#').value = 1;true;" />
<input type="hidden" name="MAX_FILE_SIZE" value="10000000" />
<input type="hidden" name="#$typeid#" id="#$typeid#" value="7" />
<xar:set name="invalid">$properties['img']->invalid</xar:set>
<xar:if condition="!empty($invalid)">
<span class="xar-error">#$invalid#</span>
</xar:if>

When you first display the form, the attach_stored field contains the upload file name, and the attach_type is 7, saying to Use the Stored File. But if you change the file input field, the attach_type is changed to 1, saying Upload the File.

Pretty neat. Well, kind of messy. But pretty cool none the less.

BTW, the other attach types are 2=External, and 5=Trusted.

An Alternative Way

Actually, this is starting to look ugly, especially having to know the innards of the Uploads module and property. Its just not what I intended. And I still don't really get it all, I mean, for example, I have not yet found the php code that actually handles the attach_type input value?!

Fortunately I'm doing this with the pageform meta-module , so have a lot of flexibility for other approaches.

Instead of faking out the uploads property, I just save a copy of the uploaded file id. Then if the user goes back and resubmits an empty filename, we pull the saved value and use that.

Here's how:

In pageform, a form is defined by a Dynamic Data (DD) object. Let's say our uploads field is named 'img'

First, add another Uploads property to the pageform DD object you're using on that form. Lets calll it 'img_save'.

Second, we'll allow the 'img' property to get posted empty. Thus we want to ignore the invald validation message from its checkInput. On the pageaction's validation_php, add this snippet:

// dont require value
if (empty($values['img'])) {
$invalids['img'] = NULL;
}

Third, in the pageaction's processing_php, add this snippet:

if (empty($values['img'])) {
// resubmitted? then use previous value
$outvalues['img'] = $values['img_save'];
$values['img'] = $values['img_save'];
}

else {
// save value (back to input object) in case go back
$values['img_save'] = $values['img'];
$outvalues['img_save'] = $values['img'];
}

In testing I found cases where I need to save a copy of the upload value in the input or output objects. So to be safe we just do it in both.

Then the showform needs only contain the tags show first above, repeated here:

<xar:set name="prop">$properties['img']</xar:set>
<xar:set name="propid">"dd_" . $prop->id . "_attach_upload"</xar:set>
<xar:set name="typeid">"dd_" . $prop->id . "_attach_type"</xar:set>
<label for="$propid" class="xar-form-label">Attach Image File: </label>
<input type="file" name="$propid" id="$propid" />
<input type="hidden" name="MAX_FILE_SIZE" value="10000000" />
<input type="hidden" name="#$typeid#" id="#$typeid#" value="1" />
<xar:set name="invalid">$properties['img']->invalid</xar:set>
<xar:if condition="!empty($invalid)">
<span class="xar-error">#$invalid#</span>
</xar:if>

 

Handling Plain Upload Fields in a Pageform

Posted by: asdf on February 20, 2007 10:45 PM
sdsfsfsdfsd

#

Post a new comment

How many days in a week?

Name :