In my form model I have this:
class UpdateForm extends Form {
public function __construct($name = null) {
parent::__construct('updateForm');
$this->setAttribute('method','post');
$this->add(array(
'name' => 'response',
'attributes' => array(
'type' => 'textarea',
),
'options' => array(
'label' => 'Response',
),
));...
In my view I was doing this:
$form->get('response')->setAttributes(array(
'class' => 'form-control',
'placeholder' => '--- Enter your response here ---'
));
I found I can set the class of a specific form input in my Form model by just doing:
$this->add(array(
'name' => 'response',
'attributes' => array(
'type' => 'textarea',
'class' => 'fart',
),...
But now I wonder if this is wise. Should I do this in the view or does it matter (assuming I am trying to adhere to MVC best practices)
Both of the options are valid.
I am not sure which one best fits the MVC approach but here's what I do. If I am working in a team and if someone else is handling the design of the application, I will add these CSS classes in the view. So the designer can change them if he/she wants to.
If I am most likely to work with a developer I assign the CSS classes in the model. And leave a comment in the view pointing out the location of the file where the classes are assigned.
Hope this help.
Related
I am using PHP Zendframework to build forms. I have service object that i need want to use to populate my ServiceEditForm.php. But in this service form i have Object of "Billing", "Subscription" and array of object "Commands". Below is my implementation of Service class.
class Service{
public $service_id;
public $ServiceName;
public $TelecomOperator;
public $SubMethod;
public $Provider;
public $active;
public $billingType;
public $subscriptionPlan;
public $commands;
function exchangeArray(array $data);}
I want to bind the object of Service class to my Edit form which used subscription, billing and commands related data as fieldsets. I am able to populate service values in form using bind but not other objects. here is my form implementation
class ServiceEditForm extends Form{
public function __construct($name = null)
{
parent::__construct('Edit Service');
$this->setAttribute('method', 'post');
$this->setAttribute('enctype','multipart/form-data');
//here i have other fields that belongs to service object
$this->add( array(
'name' => 'billingType',
'type' => 'Services\Form\BillingTypeFieldset',
'options' => array(
'label' => 'Billing Type',
),
));
$this->add( array(
'name' => 'subscriptionPlan',
'type' => 'Services\Form\SubscriptionPlanFieldset',
'options' => array(
'label' => 'Subscription Plan',
),
));
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'commands',
'options' => array(
'label' => 'commands',
'count' => 2,
'should_create_template' => true,
'allow_add' => true,
'target_element' => array(
'type' => 'Services\Form\CommandFieldset',
),
),
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Save'
),
));
}
}
As I said I am not able to populate fieldsets with bind within form with this implementation. Any suggestion will be appreciated.
Although I have already answer the question after looking up for possible solutions but Hydrator Implementations given in this link is also useful in explaining the very basics that one should read before using it. My bad i didn't went for full-throttled study before implementing fieldsets.
http://framework.zend.com/manual/current/en/modules/zend.stdlib.hydrator.html
This url explain possible implementation of hydrators that can deliver you very easy binding solution for your class.
This might be a bit strange, but I'll try to explain. Basically I have a table containing users and a table containing customers. Users have permission to look into the data of only certain customers. So I figured I would make a separate table for user permissions, taking the user ID and the customer ID as foreign keys and having one row per customer/user permission.
When the admin adds a new user to the database using a class called UserForm (posted shortened below for reference), which uses Zend\Form, I want to also display all the customers next to the form as buttons that can be selected to be added as permissions. Now, I thought I would do that by having a JavaScript array that appends or removes the customer IDs if they're selected/deselected, then passing that array to the form as a hidden value and finally looping through the array inserting a row into the permissions table for each customer ID in the array, and taking the user ID that's been created as well. I'm not sure if this is the best way to do it, but it's the best I could come up with.
Hope that's at least slightly understandable. So, I have one form, but I want to insert into two different tables. My question, I guess, is how do I pass the array to the form as a value? And how do I insert into not only the users table, but also the permissions table, when the saveUser() method is called (I'll post that below too). Also, is this a really weird way of doing it that I'm being unnecessarily difficult about? I'd love to hear if there's a much easier way.
My UserForm class:
namespace Admin\Form;
use Zend\Form\Form;
class UserForm extends Form
{
public function __construct($name = null)
{
parent::__construct('user');
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'userId',
'attributes' => array(
'type' => 'Hidden',
),
));
$this->add(array(
'name' => 'activated',
'attributes' => array(
'value' => 1,
'type' => 'Hidden',
),
));
$this->add(array(
'name' => 'username',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Username:',
),
));
$this->add(array(
'name' => 'firstname',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'First name:',
),
));
$this->add(array(
'name' => 'lastname',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Last name:',
),
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Go',
'id' => 'submitbutton',
),
));
}
}
My saveUser() method
public function saveUser(User $user)
{
$data = array(
'firstname' => $user->firstname,
'lastname' => $user->lastname,
'username' => $user->username,
'activated' => $user->activated,
);
$userId = (int)$user->userId;
if ($userId == 0) {
$this->tableGateway->insert($data);
} else {
if ($this->getUser($userId)) {
$this->tableGateway->update($data, array('userId' => $userId));
} else {
throw new \Exception('User ID does not exist');
}
}
}
One method is to use Form Fieldsets. A form can have multiple Fieldsets, and each Fieldset can be bound to a different entity.
These are useful when you have a one to one relationship between the entities
You would then create teo entities, for example a User entity (as you already have) and a new entity to represent your Permission.
You would create a Feildset for each and bind the objects to the fields sets. (UserFieldSet and PermissionFieldset for example)
checkout the section on Form Fieldsets:
http://zf2.readthedocs.org/en/latest/modules/zend.form.advanced-use-of-forms.html
If you have a one to many relationship, ie. One User can have Many Permissions, then you would be better off looking at form Collections:
http://zf2.readthedocs.org/en/latest/modules/zend.form.collections.html
there's an example of dynamically adding new rows for a one to many relationship too.
I'm trying to work out how to filter empty records from a form collection. With my application I have 2 entities, Competition and League. A competition may have zero or more Leagues.
So I create a Competition form (CompetitionForm), a Competition fieldset (CompetitionFieldset) and a League fieldset (LeagueFieldset).
The CompetitionFieldset is added to the CompetitionForm, and the CompetitionFieldset uses Zend\Form\Element\Collection to allow the user to add 1 or more Leagues. I've added the current code for each class below.
By default, I want to display input fields for 3 leagues within a competition, so within the CompetitionFieldset, when I add the Zend\Form\Element\Collection item, I set the count option to 3.
But if a user doesn't supply any data for the leagues, I want to ignore them. At present, three empty associated leagues are created within my database.
If I set an InputFilter on the LeagueFieldset to make the name field required for example, then the form won't validate.
I should maybe also mention that I'm using Doctrine2 to model my entities and hydrate my forms etc.
I'm sure I could make it work with some additional code on my models, or even in my Controller where I process the form, but I'm sure there is a neater solution maybe using Filters.
If anyone could point me in the right direction it would be much appreciated.
Many thanks in advance for any help you can provide.
:wq
familymangreg
My CompetitionForm
use Kickoff\Form\AbstractAdminForm;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Zend\Stdlib\Hydrator\ClassMethods;
class CompetitionForm extends AbstractAdminForm
{
public function __construct(ObjectManager $objectManager)
{
parent::__construct($objectManager, 'competition-form');
$fieldset = new CompetitionFieldset($objectManager);
$fieldset->setUseAsBaseFieldset(true);
$this->add($fieldset);
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Submit',
'id' => 'submitbutton',
),
));
}
}
My CompetitionFieldset
use Kickoff\Form\AbstractFieldset;
use Kickoff\Model\Entities\Competition;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
class CompetitionFieldset extends AbstractFieldset
{
public function __construct(ObjectManager $objectManager)
{
parent::__construct($objectManager,'Competition');
$this->setHydrator(new DoctrineHydrator($this->objectManager,'Kickoff\Model\Entities\Competition'))
->setObject(new Competition());
$this->setLabel('Competition');
$this->add(array(
'name' => 'name',
'options' => array(
'label' => 'Competition name (e.g. Premier League)',
),
'attirbutes' => array(
'type' => 'text',
),
));
$this->add(array(
'name' => 'long_name',
'options' => array(
'label' => 'Competition long name (e.g. Barclays Premier League)',
),
'attirbutes' => array(
'type' => 'text',
),
));
$leagueFieldset = new LeagueFieldset($objectManager);
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'leagues',
'options' => array(
'label' => 'Leagues',
'count' => 3,
'should_create_template' => true,
'allow_add' => true,
'target_element' => $leagueFieldset,
),
));
}
}
My LeagueFieldset
use Kickoff\Form\AbstractFieldset;
use Kickoff\Model\Entities\League;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Zend\InputFilter\InputFilterProviderInterface;
class LeagueFieldset extends AbstractFieldset implements InputFilterProviderInterface
{
public function __construct(ObjectManager $objectManager)
{
parent::__construct($objectManager,'League');
$this->setHydrator(new DoctrineHydrator($this->objectManager,'Kickoff\Model\Entities\League'))
->setObject(new League());
$this->setLabel('League');
$this->add(array(
'name' => 'name',
'options' => array(
'label' => 'League name (e.g. First Qualifying Round)',
),
'attirbutes' => array(
'type' => 'text',
),
));
$this->add(array(
'name' => 'long_name',
'options' => array(
'label' => 'League long name (e.g. UEFA Champions League First Qualifying Round)',
),
'attirbutes' => array(
'type' => 'text',
),
));
}
public function getInputFilterSpecification()
{
return array(
'name' => array(
'required' => true,
)
);
}
}
You need to get data from request before you pass it to EntityManager, that's for sure. Just add your own validation to filter empty records. You can also provide javascript filters that will catch submit form event and delete empty fields before submitting it.
I have duplicated data across my config/form_validation.php and my controller.
the field and label from form_validation is the same that I specify in my controller for the id, name and placeholder
Do I have to extract that data to yet a third location and reference it in both of these?
application/config/form_validation.php
$config = array(
'register' => array(
array(
'field' => 'register_username',
'label' => 'Username',
'rules' => 'trim|required|exact_length[5]'
),
.....
application/controllers/mycontroller.php
$this->viewdata['register_username'] = array(
'id' => 'register_username',
'name' => 'register_username',
'type' => 'text',
'placeholder' => 'Username'
);
...
I'm not sure why you have your data duplicated in the controller itself. You might find it easier to use Jamie Rumbelow's model/schema libraries mashup.
This will clean up your model/application structure as a whole. The model extension library itself allows for the automation of CRUD methods.
in a custom module with admin pages, in the file
app\code\local\Namespace\Mymodulw\Block\Myblock\Edit\Tab\Form.php
you can add somthing like this
$fieldset->addField('title', 'text', array(
'label' => Mage::helper('mymodule')->__('Title'),
'class' => 'required-entry',
'required' => true,
'name' => 'title',
));
this create an input of type text in the edit page, what i'm trying to do is create a new type, then i can make something like this
$fieldset->addField('title', 'mytype', array(
'label' => Mage::helper('mymodule')->__('Title'),
'class' => 'required-entry',
'required' => true,
'name' => 'title',
));
can you see the diference??
thanks
The adminhtml field types extend Varien_Data_Form_Element_Abstract and are located in \lib\Varien\Data\Form\Element. So you would need to create a new file called Mytype.php with a declaration of class Varien_Data_Form_Element_Mytype extends Varien_Data_Form_Element_Abstract and then override the Abstract methods to function as you need.
Check out the files in that directory for examples.
Cheers,
JD