Dynamic (jquery-based) forms for editing custom blocks

Permalink
Hi all!

I am looking for ways to effectively
modify the edit form of a custom block dynamically by jquery, i.e. change the number of form elementsdepenedet on user input.
It would be necessary to intercept loading of
the edit form dialog and also the submit event.
Unfortunately I do not see a way to achieve this without modifying the c5 core javascript files, as there seem to be no c5-specific event hooks to use (e.g. some kind of onload event for the edit dialog).

Perhaps anyone can point me in the right direction, whether there are any provisions
for this special case of modifying behaviour.

Thanks!

 
jordanlev replied on at Permalink Reply
jordanlev
Hi,
If you're building a custom block then you have 100% flexibility to add whatever javascript you want.

If you're talking about the add.php and edit.php forms, you can put javascript in a file called "auto.js" (in your block directory), and it will automatically be loaded. Or if you need to add more than just 1 file or you want the file to be named something else, you can put this in your block controller:
public function on_page_view() {
   $html = Loader::helper('html');            
   $bv = new BlockView();
   $bv->setBlockObject($this->getBlockObject());
   $this->addHeaderItem($html->javascript($bv->getBlockURL() . 'my_javascript_file.js'));
   $this->addHeaderItem($html->javascript($bv->getBlockURL() . 'my_other_javascript_file.js'));
}


Hope that helps!

-Jordan

FYI, you might get more responses if you post this to the "Building With C5" forum instead of here -- seems like most developers only ready that one.
texaveray99 replied on at Permalink Reply
Thank you for this info, that might be helpful.
But there is an additional problem that I
want to modify a block form dynamically by jquery which by itself is an easy task.
But up to now it's not clear to me, which additional actions are required on my part to get additional form items data sent to the server (I guess, there is some registration action necessary).
My actual problem is, that I do not understand the javascript/Ajax/Formprocessing framework, that I do need to modify.
I could not find much documentation on that topic and it's rather time consuming to reverse engineer it all.
Perhaps someone can point me in the right direction.

Thanks!
jordanlev replied on at Permalink Best Answer Reply
jordanlev
I'm still a little confused about whether you're building a custom block that has your own form in it (like you're putting <form> and <input> tags into the view.php file of your block), or are you trying to extend the built-in concrete5 "form" block?

If you're trying to extend c5's built-in form block, you should take a look at a community modification that makes the form block more "MVC" style, which should give you the flexibility you're looking for:
http://www.concrete5.org/community/forums/customizing_c5/updating_f...
(scroll down to the post titled "Version with Labels - Improved CSS Styling Capability" and click the paperclip icon at the bottom of that comment to download it).

If you are building your own block with a form in it from scratch, the general idea is this:

In your block's view.php file, output the form:
<?php $form = Loader::helper('form'); ?>
<form method="post" action="<?php echo $this->action('submit_form'); ?>">
<?php echo $form->label('someText', 'Some Text:'); ?>
<?php echo $form->text('someText'); ?>
<?php echo $form->submit('submit', 'Submit'); ?>
</form>

Add as many or as few fields as you want (or use javascript to dynamically add fields if you want), but the key is using "$this->action()" as the form's action. This outputs a url that goes to a specific function in your block's controller (a function whose name is the word "action_" followed by the string you pass to the $this->action() function). Inside that function, you can retrieve the values of any form fields (regardless of whether they were in the view.php file's original html or if you added them dynamically via javascript) using the "$this->post('fieldName')" function. For example, here is the controller code that would respond to the above form:
public function action_submit_form() {
   //Get form values like this:
   $someText = $this->post('someText');
   //Do whatever you want with it (save to database, send email, whatever)...
   //...
   //When you're done, you should redirect back to the page so the form clears out
   // and so that when the user hits the "Back" button they aren't prompted for a form resubmit.
   if ($someText) {
      $redirect = BASE_URL . View::url(); //Location headers should be absolute URI's (seehttp://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.30)...
      header("Location: " . $redirect);
      die;
   } else {
   //If there was a problem, do NOT redirect back to this page -- it will be re-displayed,
   // and if you used the form helper methods in view.php (like in the example above),
   // the previously-entered values will automatically be filled in by C5.


Hope that clears things up -- if not, perhaps you could be a little more specific about what exactly you are trying to accomplish?

Good luck!

-Jordan

UPDATE: There's some more info about how to do ajax form submissions here:
http://www.concrete5.org/documentation/how-tos/javascript-jquery-an...
texaveray99 replied on at Permalink Reply
Thank you very much for so much useful information!

As a matter of fact I finally found a rather simple solution while digging deeper into jquery, ajax and the livequery plugin.
To make the problem a bit more clear:

I created a custom block type with some simple edit.php and add.php forms. No problems up to this point, but in order to enhance usability, I wanted to give the user the possibility to add a new form input element for optional data. On submission I needed to evaluate optional input elements to save them in one single field that directly maps to the backend data table. As I figured out this is rather easily done by jquery dom manipulation commands, changing the html input elements attributes accordingly. I only missed renaming the name attribute, so I could not retrieve the optional values in the block controller's overridden save method (where I included the necessary preprocessing).

The final problem was calling a javascript method when calling the edit.php form on the custom block in order to modify the form. This was necessary because one table column contained aggregated data that needed to be split into several text input elements. Using the jquery/livequery plugin it was quite simple to intercept the event occurring, when the edit dialog is called.

It was not actually necessary to do it in javascript (as opposed to serverside in php), but I was feeling to be more consistent doing it this way.
jordanlev replied on at Permalink Reply
jordanlev
UPDATE (almost a year later):
If you need to include other javascript files besides auto.js in your block add/edit form, add this to the top of your block's add.php and/or edit.php file:
<script type="text/javascript">
    ccm_addHeaderItem('<?php echo $this->getBlockURL(); ?>/your.javascript.file.name.js', 'JAVASCRIPT');
</script>