I currently have a view, manage, that lists data items. Instead of running “edit” and “add” actions with separate views, I’m having the appropriate form display inline in the page when it is needed. On the form is a “cancel” button that will hide it.
Right now I decide what, if any, form to display inline through a GET parameter called mode. So /controller/manage will display the items, while /controller/manage?mode=edit will display the items and show the edit form for the correct data item.
The action accepts various other GET parameters such as a date interval.
In order to activate the form, I’m generating a link to the current action with the mode parameter spliced in with existing parameters in $_GET. I’m using the following one-liner:
<?php echo CHtml::link('Edit', array_merge(array('/session/manage', 'mode' => 'edit', 'id' => 6), $_GET)); ?>
To implement the “cancel” link, I’m using:
<?php echo CHtml::link('Cancel', array_diff(array_merge(array('/session/manage'), $_GET), array('edit'))); ?>
My question is: is there a cleaner way to do this? While this works, it feels like a hack. I haven’t found any documentation on generating URLs that include existing GET parameters. Does Yii provide a built-in method to do what I want to do? Should I re-evaluate my general approach to conditional views, which might in turn yield a cleaner solution?
One way would be to hold all of the most recent _GET variables in session state. Your controller would then act on that stored data and use new _GET variables to override it. Using that method, you wouldn’t need to merge the existing _GET variables back into the new request. The tradeoff is that you end up having to manage that session data and handle possible special cases (like starting over with fresh state).
Another way would be to use Ajax to call an action that returns a partial view with your rendered edit form. Then your links would just need to call some javascript that does the Ajax call with the current ID and displays the returned form on the page. Your links would end up looking something like this:
<a href="#" onclick="showEdit(6)">Since using Ajax wouldn’t cause the page to reload, you don’t need to worry about any of the _GET parameters required to show your list. And your Cancel link would become a javascript call to simply remove the edit form from the DOM. Using jQuery:
$('#editform').remove();Another way to make it a little cleaner would be to encapsulate all of the
array_merge()stuff up there into a method of a custom component or helper. Then your code could look something like:echo CHtml::link('Edit', URLHelper::mergeGet(array('/session/manage', 'mode' => 'edit', 'id' => 6));or even ecapsulate that in your own CHtml class:
echo MyCHtml::link('Edit', array('/session/manage', 'mode' => 'edit', 'id' => 6));where
MyCHtml::link()does everything thatCHtml::link()does in addition to thearray_mergestuff. MyCHtml could even extend CHtml so that it has all of CHtml’s methods.