How can we change the admin form element position in magento? - magento

How can we change the position (Sort Order) of admin form element?

TL;DR:
You can specify a caret ^ as an optional fourth argument when defining your field:
$fieldset->addField('my_element','text',array(
'name' => 'my_element',
'label' => Mage::helper('customer')->__('My Element')
),'^');
More Information
See Varien_Data_Form_Abstract::addField:
/**
* Add child element
*
* if $after parameter is false - then element adds to end of collection
* if $after parameter is null - then element adds to befin of collection
* if $after parameter is string - then element adds after of the element with some id
*
* #param string $elementId
* #param string $type
* #param array $config
* #param mixed $after
* #return Varien_Data_Form_Element_Abstract
*/
public function addField($elementId, $type, $config, $after=false)
{
if (isset($this->_types[$type])) {
$className = $this->_types[$type];
}
else {
$className = 'Varien_Data_Form_Element_'.ucfirst(strtolower($type));
}
$element = new $className($config);
$element->setId($elementId);
if ($element->getRequired()) {
$element->addClass('required-entry');
}
$this->addElement($element, $after);
return $element;
}
The comments tell you how to order your elements. So, to position your field, specify a fourth argument $after of somefield or whatever is the ID of the field you wish to place yours after.
This is useful when you are extending the customer account form within your own class. Here's an example that places a new form element above the first in the form:
class Yourcompany_Adminhtml_Block_Customer_Edit_Tab_Account extends Mage_Adminhtml_Block_Customer_Edit_Tab_Account {
...
public function initForm() {
parent::initForm();
$form=$this->getForm();
$fieldset=$form->getElement('base_fieldset');
$fieldset->addField('my_element','text',array(
'name' => 'my_element',
'label' => Mage::helper('customer')->__('My Element')
),'^');
return $this;
}
...
}
You may notice something strange. My fourth argument to the addField call is a caret ('^'). This places the element at the very top of the form, which is what you appear to be asking in your question.
But wait! Why doesn't this match up to the code documentation shown above?! Well, it looks like a disconnect in consistent coding convention during development. If you follow the code, you will find that addField makes it way to the Varien_Data_Form_Element_Collection::add method. It is in here that we see a 2nd argument, $after, which notes in the comments:
/**
* Add element to collection
*
* #todo get it straight with $after
* #param Varien_Data_Form_Element_Abstract $element
* #param boolean|'^'|string $after
* #return Varien_Data_Form_Element_Abstract
*/
public function add(Varien_Data_Form_Element_Abstract $element, $after=false)
Here we find that false appends the element to the fieldset, a ^ character prepends the element, and passing in an element ID will place the element after the one specified.
UPDATE: How to Deal With Existing Fields
What if you want to re-order an existing field? Unfortunately, ordering takes places at the time of adding the field, and cannot conveniently be changed after that. But I can offer 2 approaches to get the job done.
Method 1: Re-Order by Removing and Adding Again
$fieldset->removeField('core_element');
$fieldset->addField('core_element','text',array(
'name' => 'core_element',
'label' => Mage::helper('customer')->__('Core Element')
),'^');
This is a simple solution, but requires you to manually re-define that field. In some cases this will be easy enough. In others, not so. For those scenarios, see next.
Method 2: Re-Order by Cloning
$element=clone $form->getElement('core_element');
$fieldset->removeField('core_element');
$fieldset->addElement($element,'^');
I think this is the best solution, because it preserves the element definition as it was originally written. This is especially important in the case of attributes whose fields are generated in part by their frontend_input_renderer classes. Learn more about that here.

Check the 'attribute_id' & 'sort_order' fields in 'customer_eav_attribute' table.

Related

How to clean / reduce properties of a model instance to reduce json size?

I have a process where some models are updated and after that I send the updated object to pusher for real time tracking through an control board but the object has several other objects as relationships so the size of the serialized object exceed the pusher limit size for a message so my question is how can I delete some properties of the related objects?
I already tried pluck function but I don't know how to use on neastead objects
$vehicleEntry = VehicleEntry::with('vehicle')->find($request->entryId);
// I need just the id and plate of the object
$vehicleEntry->pluck('vehicle.id', 'vehicle.plate');
but it gets error
{id: 1, vehicle: {id: 2, plate: 'JIS575'}, created_at: '2019-07-11'}
One way I personally prefer is to make use of API resources. This way you always have full control over the data that is being returned.
Example:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class VehicleEntryResource extends Resource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => (int) $this->resource->id,
// Watch out with this. Make sure the vehicle relation is loaded.
// Otherwise it will always add this execute another query for
// every vehicle entry you send to this class, would be bad when
// you want to send multiple. You could also use
// $this->whenLoaded('vehicle'), however this needs another
// resource.
'vehicle' => [
'id' => (int) $this->resource->vehicle->id,
'plate' => $this->resource->vehicle->plate,
],
'created_at' => $this->resource->created_at,
];
}
}
Now you can call this anywhere you want:
new VehicleEntryResource($vehicleEntry);
Not sure if Pusher messages works as nice as the JsonResponse you generally would return in your controller. When returning it in a response it would convert them to arrays automatically. But you could also do the following to get the array representation:
(new VehicleEntryResource($vehicleEntry))->toArray(null);
A simple way to do this is to add a $hidden property to your model and give it an array of strings that are property names you'd like to hide from json output:
protected $hidden = [
'hide',
'these',
'attributes',
'from',
'json'
];
When your object is converted to json it will automatically prevent any attributes listed in the $hidden array from showing up.
See the docs here: https://laravel.com/docs/5.8/eloquent-serialization#hiding-attributes-from-json

Laravel Form Validations

I am validating number field below code is working fine. It is checking the characters should not be more then 2 or less, which is fine for me.
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'id' => 'required|min:2|max:2',
'title' => 'required'
];
}
But when I add more validation rule like (numeric), min and max validaiton rules get changed, now it is being checked by the numeric number should not be greater than 2... WHY? IS IT BUG?
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'id' => 'required|min:2|max:2|numeric',
'title' => 'required'
];
}
the min and max rule depend on the type of the field. If it is a string it will check the length. If it is a number it will check the value.
So if you want to have numbers only with two chars set use
'id' => 'required|min:10|max:99|numeric',
The field under validation must have a size matching the given value. For string data, value corresponds to the number of characters. For numeric data, value corresponds to a given integer value. For files, size corresponds to the file size in kilobytes.

Joomla fields : change dynamically the readonly property

in Joomla component forms :
is there a way to dynamically change the form field property : "readonly" ?
example :
if( _condition_ )
$this->form->getInput('Name')->readonly = true;
From what I saw in the API, you basically can change it.
I see it like this:
When you call $this->form->getInput('Name') you are inside JFormField object (actually inside an class which interits JFormField, which is abstract - inherited by JFormFieldText for example), calling the method getInput().
This method, getInput(), gets its parameters $element ( SimpleXMLElement object of the XML element that describes the form field.) from what I can see directly from the XML you defined and it returns just a string (actual HTML), so setting and non existing property obviously won't work.
But JForm has a nice method called setFieldAttribute(), see signature below:
/**
* Method to set an attribute value for a field XML element.
*
* #param string $name The name of the form field for which to set the attribute value.
* #param string $attribute The name of the attribute for which to set a value.
* #param mixed $value The value to set for the attribute.
* #param string $group The optional dot-separated form group path on which to find the field.
*
* #return boolean True on success.
*
* #since 11.1
*/
public function setFieldAttribute($name, $attribute, $value, $group = null)
So your code can look like:
if( _condition_ )
{
$this->form->setFieldAttribute('Name', 'readonly', 'true', $group = null);
echo $this->form->getInput('name');
}
Hope this helps.

how we can add rule in Yii model for input must be greater than 0

do anyone know how can I apply rule in Yii model for input must be greater than 0 value, without any custom approach ..
like :
public function rules()
{
return array(
....
....
array('SalePrice', 'required', "on"=>"sale"),
....
....
);
}
many thanks ..
Simpler way
array('SalePrice', 'numerical', 'min'=>1)
with a custom validator method
array('SalePrice', 'greaterThanZero')
public function greaterThanZero($attribute,$params)
{
if ($this->$attribute<=0)
$this->addError($attribute, 'Saleprice has to be greater than 0');
}
I see it is a price so you could use 0.01 (a penny) as a minimum value like so:
array('SalesPrice', 'numerical', 'min'=>0.01),
Note that this solution does not validate that the number entered is a price, just that it is > 0.01
I know I am too late for this . But just for future reference you can use this class also
<?php
class greaterThanZero extends CValidator
{
/**
* Validates the attribute of the object.
* If there is any error, the error message is added to the object.
* #param CModel $object the object being validated
* #param string $attribute the attribute being validated
*/
protected function validateAttribute($object,$attribute)
{
$value=$object->$attribute;
if($value <= 0)
{
$this->addError($object,$attribute,'your password is too weak!');
}
}
/**
* Returns the JavaScript needed for performing client-side validation.
* #param CModel $object the data object being validated
* #param string $attribute the name of the attribute to be validated.
* #return string the client-side validation script.
* #see CActiveForm::enableClientValidation
*/
public function clientValidateAttribute($object,$attribute)
{
$condition="value<=0";
return "
if(".$condition.") { messages.push(".CJSON::encode($object->getAttributeLabel($attribute).' should be greater than 0').");
}";
}
}
?>
Just make sure this class is imported before use.
Did nobody check the docs?
There is a built-in validator CCompareValidator:
['SalePrice', 'compare', 'operator'=>'>', 'compareValue'=>0]
you can use this one too:
array('SalePrice', 'in','range'=>range(0,90))
I handled this by regular expression, may be it will help too ..
array('SalePrice', 'match', 'not' => false, 'pattern' => '/[^a-zA-Z0]/', 'message' => 'Please enter a Leader Name', "on"=>"sale"),
many thanks #sdjuan & #Ors for your help and time ..

Magento set subscriber first & last name

When someone subscribes to the Magento newsletter I also want them to fill in their first and last name. I have added the two input fields to the form. The field names are 'firstname' and 'lastname'.
I'm going to extend Mage/Newsletter/controllers/SubscriberController.php
In newAction():
I have retrieved the post variables here:
$email = (string) $this->getRequest()->getPost('email');
$firstname = (string) $this->getRequest()->getPost('firstname');
$lastname = (string) $this->getRequest()->getPost('lastname');
I have added the following code after the success message:
$subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($email);
$subscriber->setEmail("example#email.com");
$subscriber->setFirstname("ADAM");
$subscriber->setLastname("MOSS");
$subscriber->save();
I just want to get the first and last name method working - the setEmail part works perfectly. I looked in Model/Subscriber.php and saw that there's no function for setting subscriber names.
Looking at the grid in the admin I also noticed that it says 'Customer First Name' and 'Customer Last Name' so I assume the names belong to the customer model rather than the subscriber model.
Is there a way around this? I want to be able to assign the customer name to the subscriber when they subscribe to the newsletter. I tried the observer method mentioned on this post, but I think the same issue exists: Adding a custom field to Magento's subscription module
Any help would be much appreciated.
Take a look at newsletter_subscriber table in the database. There is no firstname or lastname. You set these fields only on the newsletter model.
The subscribe() method from subscriber model associate the subscriber to customer id so the grid shows indeed the customer firstname and lastname.
If you want to have these fields also for subscribers that are not associated to cutomers you should modify the newsletter_subscriber database table by adding these two fields.
You must create a local copy of:
app/code/core/Mage/Newsletter/controllers/SubscriberController.php
app/code/core/Mage/Newsletter/Model/Subscriber.php
In app/code/core/Mage/Newsletter/controllers/SubscriberController.php add after line 44:
$firtname = (string) $this->getRequest()->getPost('firstname');
$lastname = (string) $this->getRequest()->getPost('lastname');
Then change from:
$status = Mage::getModel('newsletter/subscriber')->subscribe($email);
to:
$status = Mage::getModel('newsletter/subscriber')->subscribe($email,$firtname,$lastname);
Now in app/code/core/Mage/Newsletter/Model/Subscriber.php edit the subscribe function signature at line 307 from:
public function subscribe($email)
to:
public function subscribe($email,$firstname,$lastname)
Add this after line 338:
$this->setSubscriberFirstname($firstname);
$this->setSubscriberLastname($lastname);
And add the getters and setters for it:
/**
* Alias for getSubscriberFirstname()
*
* #return string
*/
public function getFirstname()
{
return $this->getSubscriberFirstname();
}
/**
* Alias for setSubscriberFirstName()
*
* #param string $value
*/
public function setFirstname($value)
{
return $this->setSubscriberFirstname($value);
}
/**
* Alias for getSubscriberLastname()
*
* #return string
*/
public function getLastname()
{
return $this->getSubscriberLastname();
}
/**
* Alias for setSubscriberLastname()
*
* #param string $value
*/
public function setLastname($value)
{
return $this->setSubscriberLastname($value);
}
You also need to add firstname and lastname columns to newsletter_subscriber as said in the other anwser.

Resources