Silk is finally getting to that position where it’s about ready. All of the pieces that I’ve been putting together over the past few months are all starting to fall correctly into place and it’s getting usable.
I spent a lot of time over the last week working on the display portion of the system, mainly views, controller output, partials and javascript. Still a bunch of work to do, but I at least have results to work — now I can just refine.
Last night, I tested the concept of doing a very simple AJAX form, and it went better than I had hoped. Here’s the recap…
Create a controller. Being unoriginal, I called it TestController.php. It would go into the app/controllers directory. It would look something like:
use \silk\action\Controller; use \silk\form\Form; class TestController extends Controller { function index() { $form = new Form('test_form', array('remote' => true)); $fs = $form->addFieldSet('field_set', array('legend' => 'Config Options')); $fs->addField('TextBox', 'field1', array()); $form->addButton('Submit', array('disable-with' => 'Submitting...')); if ($form->isPosted()) { $form->fillFields(); if (!endsWith($fs['field1']->value, 'was here')) $fs['field1']->value .= ' was here'; } $this->set('form', $form); } }
The 10,000 meter view is that we’re basically creating a form object. What makes it an ajax form is simply the 'remote' => true in the Form constructor.
Silk is using a style of javascript called UJS, which was made popular by Rails. Without going crazy w/ the details, the idea is that various hooks to the javascript can be created by simple HTML5 data-* tags embedded into the html. The remote basically adds a data-remote='true' to the form tag when output, and the UJS javascript takes it from there.
After that, we check to the see if the Form was submitted. If it was, we fill in the Form object with the values that were posted. Then, it’s just a simple check and append of “ was here” to the value that was input. Last, but not least, we set our form object to be visible to the views/template engine.
Next, create yourself a default view in app/views/test/index.html.tpl. The naming is important here. It’s basically saying that you want to have a view that a. responds to the index action, b. responds to only html requests, and c. is a Smarty template. It can very simply look like this:
{partial name="_form"}This just renders a partial template called form in a div. This partial would be in app/views/test/_partial.tpl (it’s a Smarty template, and responds to all actions — html, js, etc) and would look something like:
{$form->render()}Yup, that’s it. This takes the $form object set by the controller, and renders it to the browser with all of the form rendering defaults. Not fancy, but functional. Now, if you go to http://my.silk.vhost/test, you should get the form in all it’s glory.
However, if you fill in the text and hit submit, it won’t do anything. At least it won’t look like it, because the framework will call a 404. The reason is because the main view (index.html.tpl) is only looking for html requests, and since we set remote to true in our Form, it’s sending a AJAX=y ‘js’ request instead. Since the view doesn’t response to js requests that are beneath it, it says nothing is there and moves on.
In order to return back our updated form declaring that “value was here”, we need another view specifically for the js request. We would call that index.js.tpl, and it would look like the following:
$('#form_me').html({partial name="_form" js=true});
Again, yes, that’s it. We call our same partial, appending the js=true parameter. Behind the scenes, this runs the output through json_encode so that we don’t have to worry about improperly escaped values being sent back to the browser. The beauty here is that we’re using the same exact partial in the same exact way as the html version. The only difference is that we’re dynamically replacing the contents of the #form_me div w/ jQuery instead of refreshing the page.