ZF2, how to create form view helper? - zend-form

I want to change the way ZF2 shows the form elements. I think I have to create my own view helper but I don't know how.
I Googled for it but didn't find any useful resource.

See the SourceCode of existing Zend\Form\View\Helper*
Basically you extend those and overwrite the required functions of stuff you want to modify.
After that you'll need to register your very own view helper. This is easily done within Module.php's getViewHelperConfig()
public function getViewHelperConfig()
{
return array(
'invokables' => array(
'customViewHelperCallName' => 'Namespace\Form\View\Helper\Classname'
)
);
}

Related

Laravel 5.3 Route model binding with multiple parameters

Is it possible to have route model binding using multiple parameters? For example
Web Routes:
Route::get('{color}/{slug}','Products#page');
So url www.mysite.com/blue/shoe will be binded to shoe Model, which has color blue.
First of all, it would feel more natural to have a route like the following:
Route::get('{product}/{color}', 'Products#page');
and to resolve product by route binding, and just use the color parameter in the controller method directly, to fetch a list of blue shoes for example.
But let's assume that for some reason it's a requirement. I'd make your route a bit more explicit, to start with:
Route::get('{color}/{product}', 'Products#page');
Then, in the boot method of RouteServiceProvider.php, I would add something like this:
Route::bind('product', function ($slug, $route) {
$color = $route->parameter('color');
return Product::where([
'slug' => $slug,
'color' => $color,
])->first() ?? abort(404);
});
first here is important, because when resolving route models like that you effectively want to return a single model.
That's why I think it doesn't make much sense, since what you want is probably a list of products of a specific color, not just a single one.
Anyways, I ended up on this question while looking for a way to achieve what I demonstrated above, so hopefully it will help someone else.
Do not forget to declare the parameter types:
Route::delete('safedetail/{safeId}/{slug}', [
'as' => 'safedetail.delete',
'uses' => 'SafeDetailController#destroy',
])->where([
'safeId' => '[0-9]+',
'slug' => '[a-z]+',
]);
Try changing your controller to this:
class Pages extends Controller{
public function single($lang, App\Page $page){
dd($page);
}
}
You must add the Page Model.

Creating Prestashop back-office module with settings page

I'm creating a back-office module for Prestashop and have figured out everything except the best way to display the admin page. Currently I'm using the renderView() method to display the content of view.tpl.
I would like to display a table with values and an option to add a new row. Should I just create it in the view.tpl or is there a better way? I've seen the renderForm() method but haven't figured out how it works yet.
The biggest question I have is, how do I submit content back to my controller into a specific method?
ModuleAdminController is meant for managing some kind of records, which are ObjectModels. Defauly page for this controller is a list, then you can edit each record individually or view it's full data (view).
If you want to have a settings page, the best way is to create a getContent() function for your module. Besides that HelperOptions is better than HelperForm for this module configuration page because it automatically laods values. Define the form in this function and above it add one if (Tools::isSubmit('submit'.$this->name)) - Submit button name, then save your values into configuration table. Configuration::set(...).
Of course it is possible to create some sort of settings page in AdminController, but its not meant for that. If you really want to: got to HookCore.php and find exec method. Then add error_log($hook_name) and you will all hooks that are executed when you open/save/close a page/form. Maybe you'll find your hook this way. Bettter way would be to inspect the parent class AdminControllerCore or even ControllerCore. They often have specific function ready to be overriden, where you should save your stuff. They are already a part of execution process, but empty.
Edit: You should take a look at other AdminController classes, they are wuite simple; You only need to define some properties in order for it to work:
public function __construct()
{
// Define associated model
$this->table = 'eqa_category';
$this->className = 'EQACategory';
// Add some record actions
$this->addRowAction('edit');
$this->addRowAction('delete');
// define list columns
$this->fields_list = array(
'id_eqa_category' => array(
'title' => $this->l('ID'),
'align' => 'center',
),
'title' => array(
'title' => $this->l('Title'),
),
);
// Define fields for edit form
$this->fields_form = array(
'input' => array(
array(
'name' => 'title',
'type' => 'text',
'label' => $this->l('Title'),
'desc' => $this->l('Category title.'),
'required' => true,
'lang' => true
),
'submit' => array(
'title' => $this->l('Save'),
)
);
// Call parent constructor
parent::__construct();
}
Other people like to move list and form definitions to actual functions which render them:
public function renderForm()
{
$this->fields_form = array(...);
return parent::renderForm();
}
You don't actually need to do anything else, the controller matches fields to your models, loads them, saves them etc.
Again, the best way to learn about these controller is to look at other AdminControllers.

I've to show menu bar with stats like count of messages and updates, also other counts like gifts and messages count

I want to show a menu bar with stats like count of messages and updates, also other counts like gifts, new friend request and messages count.
This menu will be displayed on the all the pages.
How can I write a single method to get all the stats and render partial into the layout and forget about it?
And in other action just concentrate on the main functionality of the page. Without bothering about the menu.
How can I achieve this in Yii?
You're probably looking for a widget. You could for example extend CMenu and do the queries in init() there:
<?php
Yii::import('zii.widgets.CMenu')
class MainMenu extends CMenu
{
public function init()
{
// Do some count queries here. This is just an example,
// your implementation will differ, of course:
$newMessages = Messages::model()->new()->count();
// Now add the menu items:
$this->items = array(
array(
'label' => "$newMessages New messages",
'url' => array('messages/list'),
),
// ...
);
parent::init();
}
}
You then can use this widget in your views/layouts/main.php:
<?php $this->widget('MainMenu'); ?>
You can use beforeAction to achieve this.
As the docs say "This method is invoked right before an action is to be executed (after all possible filters.) You may override this method to do last-minute preparation for the action."
Also you can define public variables in you main controller (Components/Controller.php) so every other controller has access to these. You can then use them in your layout using $this-variable...
Hope this helps :)
You need to create a class that extends CMenu in /protected/components/extendingclassname
<?php
Yii::import('zii.widgets.CMenu');
class Notifications extends CMenu
{
public function init()
{
//query
$requestor=Yii::app()->user->name;
$count = Requests::model()->count( 'requestor=:requestor', array('requestor' => $requestor));
// Now add the menu items:
$this->items = array(
array(
'label' => "$count New messages",
'url' => array('user/notifications'),
),
// ...
);
parent::init();
}
}
?>
Then include the following line within your /layouts.main.php.Hope this helps a beginner who is not sure where to use the class.That's something Michael Härtl forgot to mention.

Yii CListview -> pagination and AjaxLink/ajaxButton

I have problems regarding with pagination and Ajax form.
Here is my code for Controller:
$dataProvider = new CActiveDataProvider('User', array(
'pagination'=>array(
'pageSize'=>10,
),
));
$this->render('users',array(
'dataProvider'=>$dataProvider,
));
For view -> users:
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_user',
);
For render _users:
echo CHtml::ajaxLink($text, $this->createUrl('admin/deleteuser',array('id'=>$data->iduser)), array('success'=>"js:function(html){ alert('remove') }"), array('confirm'=>_t('Are you sure you want to delete this user?'), 'class'=>'delete-icon','id'=>'x'.$viewid));
if i have 15 rows in a database it will only show 10 and will generate a pagination (ajaxUpdate = true) for next 5. The first 10 rows has no problem with the ajaxLink because the clientscript was generated but problem is the when I move to the next page, the ajaxLink is not working because its not generated by the pagination .
any idea? thanks
An alternate method, check this post in the yii forum. So your code will become like this:
echo CHtml::link($text,
$this->createUrl('admin/deleteuser',array('id'=>$data->iduser)),
array(// for htmlOptions
'onclick'=>' {'.CHtml::ajax( array(
'beforeSend'=>'js:function(){if(confirm("Are you sure you want to delete?"))return true;else return false;}',
'success'=>"js:function(html){ alert('removed'); }")).
'return false;}',// returning false prevents the default navigation to another url on a new page
'class'=>'delete-icon',
'id'=>'x'.$viewid)
);
Your confirm is moved to jquery's ajax function's beforeSend callback. If we return false from beforeSend, the ajax call doesn't occur.
Another suggestion, you should use post variables instead of get, and also if you can, move the ajax call to a function in the index view, and just include calls to the function from the all links' onclick event.
Hope this helps.
Not fully sure, but given past experiences I think the problem is in the listview widget itself.
If the owner of the widget is a Controller, it uses renderPartial to render the item view.
Renderpartial has, as you may or may not know, a "processOutput" parameter which needs to be set to TRUE for most of the AJAX magic (its FALSE by default).
So perhaps you can try to just derive a class of the listview and add a copy in there of "renderItems()". There you would have to change it so that it calls renderPartial with the correct parameters.
In the widget Clistview, I added afterAjaxUpdate
$jsfunction = <<< EOS
js:function(){
$('.delete-icon').live('click',function(){
if(confirm('Are you sure you want to delete?'))
{
deleteUrl = $(this).attr('data-href');
jQuery.ajax({'success':function(html){ },'url':deleteUrl,'cache':false});
return false;
}
else
return false;
});
}
EOS;
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'id'=>'subscriptionDiv',
'itemView'=>'_subscription',
'afterAjaxUpdate'=>$jsfunction,
'viewData'=>array('is_user'=>$is_user,'all'=>$all),
'htmlOptions'=>($dataProvider->getData()) ? array('class'=>'table') : array('class'=>'table center'),
)
);
and in the _user just added attribute data-href
<?php echo CHtml::ajaxLink($text, $this->createUrl('admin/deletesubscription',array('id'=>$data->idsubscription)),
array('success'=>"js:function(html){ $('#tr{$viewid}').remove(); }"),
array('confirm'=>_t('Are you sure you want to unsubscribe?'),
'class'=>'delete-icon',
'id'=>'x'.$viewid,
'data-href'=>$this->createUrl('admin/deletesubscription',array('id'=>$data->idsubscription))
)); ?>
try
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_user',
'enablePagination' => true,
);
if this doesn't solve, try including the total number of records in the data provider options as -
'itemCount' => .....,

How does one add a 'plain text node' to a zend form?

I'm trying to add a plain text node in a zend form - the purpose is to only dispay some static text.
The problem is - im not aware of any such way to do it.
I have used 'description' but that HAS to be attached to a form element.
Is there any way to simply display some text as part of a form? Zend considers everything as a form element so I cannot just print it out.
Eg:
The following will test your ability on so and so.
.
.
.
etc...
Any thoughts?
Zend has a form note view helper (Zend_View_Helper_FormNote), which you can use to add text.
Just create a new form element (/application/forms/Element/Note.php):
class Application_Form_Element_Note extends Zend_Form_Element_Xhtml
{
public $helper = 'formNote';
}
In your form:
$note = new Application_Form_Element_Note(
'test',
array('value' => 'This is a <b>test</b>')
);
$this->addElement($note);
Adding a hidden element with non-escaped description does the thing.
$form->addElement('hidden', 'plaintext', array(
'description' => 'Hello world! Check it out',
'ignore' => true,
'decorators' => array(
array('Description', array('escape'=>false, 'tag'=>'')),
),
));
Works perfectly. It is still attached to an element, which is, however, not rendered this way.
Code taken from: http://paveldubinin.com/2011/04/7-quick-tips-on-zend-form/
There might be a better way, but I created a paragraph by using a custom form element and view helper. Seems like alot of code for something so simple. Please let me know if you've found a more simplistic way to do it.
//From your form, add the MyParagraph element
$this->addElement(new Zend_Form_Element_MyParagraph('myParagraph'));
class Zend_Form_Element_MyParagraph extends Zend_Form_Element
{
public $helper = 'myParagraph';
public function init()
{
$view = $this->getView();
}
}
class Zend_View_Helper_MyParagraph extends Zend_View_Helper_FormElement {
public function init() {
}
public function myParagraph() {
$html = '<p>hello world</p>';
return $html;
}
}
A little late but thought I'd throw it in anyway for the benefit of the community.
Aine has hit the nail on the head. FormNote is what you need if you want to use text in Zend_Form. However, you can use it without needing to extend Zend_Form_Element_Xhtml. See example below:
$text = new Zend_Form_Element_Text('myformnote');
$text->setValue("Text goes here")
->helper = 'formNote';
Note that you can use both text and html with the formNote helper.
This functionality is built into Zend via Zend_Form_Element_Note.
$note = new Zend_Form_Element_Note('forgot_password');
$note->setValue('Forgot Password?');
I faced the same problem and decided is better not to use Zend_Form at all, but to use directly view helpers (like Ruby on Rails does) and validate on the model.
This one-liner works for me:
$objectForm->addElement(new Zend_Form_Element_Note('note', array('value' => 'Hello World')));