How to set custom data-attribute to option with Laravel Collective - php

I have a form, inside I have a select with some options and I'm using Laravel Collective Forms to build it, I have something like:
{!! Form::select('size', $data, $selecteds, ['multiple' => true]) !!}
All going well until here, but now I need to set a data-section attribute to each option, how can I make it?

I had to do the same thing recently. After inspecting the FormBuilder class to write my own marco I found out that the select() method actually has an undocumented fifth parameter for option attributes:
Form::select('size', $data, $selecteds, ['multiple' => true], $optionAttributes)
The index must match the value of the option, e.g.:
$optionAttributes = [
'S' => [
'data-title' => 'Small',
'data-surcharge' => '0',
],
'M' => [
'data-title' => 'Medium',
'data-surcharge' => '5',
],
'L' => [
'data-title' => 'Large',
'data-surcharge' => '10',
],
];
So I ended up writing a marco which generates this array based on a collection and then uses the default select() method. Something like that:
\Form::macro('locationSelect', function ($name, $value = null, $attributes = []) {
// Get all locations from the DB
$locations = \App\Location::all();
// Make an id=>title Array for the <option>s
$list = $locations->pluck('title', 'id')->toArray();
// Generate all data-attributes per option
$optionAttributes = [];
foreach ($locations as $location) {
$optionAttributes[$location->id] = [
'data-icon' => $location->icon,
'data-something' => $location->some_attribute,
];
}
// Use default select() method of the FormBuilder
return $this->select($name, $list, $value, $attributes, $optionAttributes);
});
Very convenient.
{{ Form::locationSelect('location_id') }}

You can pass option attributes as fifth parameter (version 5.8) like this
$optionParameters = collect($optionsArray)->mapWithKeys(function ($item) {
return [$item[id] => ['data-anything' => $item['anything']]];
})->all();
And select will look like
{!! Form::select('name', $optionsArray, null, ['class' => 'form-control', 'placeholder' => 'Select'], $optionParameters) !!}
I think it is much simpler and cleaner than creating macroses

Add it to a 4th argument which is an array:
{!! Form::select('size', $data, $selecteds, ['data-attribute' => 'John Smith', 'multiple' => true]) !!}

Related

How to have multiple products that depend on user input Laravel

I am using the srmklive/laravel-paypal package for my paypal API.
Currently, in my view I have multiple instances of this code block with varying product ids
{!! Form::open(['action' => 'PaypalController#expressCheckout']) !!}
{{ Form::hidden('item', 1) }}
{{ Form::hidden('name', 'm') }}
{{ Form::hidden('price', 25) }}
{{Form::submit('Pay via Paypal', array('class' => 'btn-info btn'))}}
{!! Form::close() !!}
However, when I use this method with my getCart function,
if($product == 1) {
return [
'items' => [
[
'name' => 'Mystery Core',
'price' => 25,
'qty' => 1,
],
],
'return_url' => url('/paypal/express-checkout-success'),
'invoice_id' => config('paypal.invoice_prefix') . '_' . $invoice_id,
'invoice_description' => "Order #" . $invoice_id . " Invoice",
'cancel_url' => url('/'),
'total' => 25,
];
}
}
the variables return null since they're coming from paypal's end, giving me a null error.
"Trying to access array offset on value of type null"
How can I go about having multiple products? I have heard of the addOptions function but I cannot understand it.
Even a different package suggestion is welcome!

Using radioList method with ActiveField in Yii2 to provide different options per radio box

I'm using the radioList method within the ActiveField widget and I'm trying to work out how to set different options for different radio boxes within the same list.
I have this...
$form->field($model, 'some_question')->inline()->radioList(
[
1 => Yii::t('general', 'Yes'),
0 => Yii::t('general', 'No')
],
['itemOptions' => ['value' => 1, 'data-foo' => 'bar']]
)->label(false);
But whatever I set in itemOptions gets set on all radio buttons - is there a way to set different values for each one?
Use callable item for this.
$form->field($model, 'some_question')->inline()->radioList(
[
1 => Yii::t('general', 'Yes'),
0 => Yii::t('general', 'No')
],
['item' => function ($index, $label, $name, $checked, $value) {
switch ($value) {
// different options per value
case 1:
$options = [
'data-foo' => 'bar'
];
break;
case 0:
$options = [
'data-next' => 'smthng'
];
}
return \yii\bootstrap\Html::radio($name, $checked, array_merge($options, [
'value' => $value,
'label' => \yii\bootstrap\Html::encode($label),
]));
}]
)->label(false);

Yii2 Krajee TreeViewInput widget , how to use multiple select?

I have three tables like this :
objects (id , name , tags , ...)
tags (id , name , ...)
object_tags(id , objectID , tagID)
I used krajee treeView input and in my "objects" form I have :
$form->field($model, 'tags')->
widget(\kartik\tree\TreeViewInput::className(),[
'name' => 'kvTreeInput',
'value' => 'false', // preselected values
'query' => Tags::find()->addOrderBy('root, lft')->name,
'headingOptions' => ['label' => 'تگ'],
'rootOptions' => ['label'=>'<i class="fa fa-building"></i>'],
'fontAwesome' => true,
'asDropdown' => true,
'multiple' => true,
'options' => ['disabled' => false]
]);
But I have no idea how should I write the codes in my controller or in my model!!!
In your action you should iterate over the post result
This is just a brief suggestion you must add the code related to your specific need
public function actionYourAction()
{
$post = Yii::$app->request->post();
if (!empty($post)){
$postTags = $post['tags'];
foreach ($postASCCId as $key => $value) {
$modelNew = new YourModel();
$modelNew->tag = $value;
$modelNew->save();
}
}
.....
}

Yii2 GridView - attribute format based on value of other attribute

I made custom currency formatter + converter based on values from database.
This is how I use it in DetailView
use yii\helpers\Html;
use app\commands\AppHelper;
use yii\widgets\DetailView;
use app\models\Part;
<?= DetailView::widget([
'model' => $model,
'attributes' => [
// ...
[
'attribute' => 'price',
'label' => (new Part())->getAttributeLabel('price_user'),
'format' => [
'currency',
AppHelper::getUserCurrencyCode(),
[
'convert' => true,
'currencyFrom' => $model->currency->code,
'currencyTo' => AppHelper::getUserCurrencyCode(),
],
],
],
// ...
],
]) ?>
In this widget I can accomplish behaviour like this: when there is numeric value, it gets formatted, if there is NULL value, usual (not-set) is printed out...
Notice $model->currency->code which is data from relation, in DetailView easily accessible but I can not figure out how to get that data into formatter in GridView.
Problem is when I want to format data in GridView.
I allow NULL values on column that I need to use formatter on, so I already threw away idea of using
'value' => function ($data, $key, $index, $column) { return $data->value; }
because when NULL value is present, yii sends data like this
<span class="not-set">(not set)</span>
and either I want to let it be or set my custom value (considering different value for other columns with NULL value) and I also want to save trouble handling all those (not set) values.
Another reason is, as I noticed, that if I use 'format' => ... in attribute params, formatting happens before setting those (not set) values.
So I was thinking about somehow passing that $model->currency->code, which is data from relation, to that formatter.
Any ideas? Thanks.
Worst case scenario I will use formatter in value dumping values that contains '<span' or NULL like this, but it is ugly and I dont like it...
EDIT: I added custom static method to format unset data. I still dont like it, but hey, it works ... :D
use yii\helpers\Html;
use app\commands\AppHelper;
use yii\grid\GridView;
use app\models\Part;
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
// ...
[
'attribute' => 'price',
'label' => (new Part())->getAttributeLabel('price_user'),
'value' => function ($data, $key, $index, $column) {
return Part::requestPrice(Yii::$app->formatter->asCurrency(
$data->price,
AppHelper::getUserCurrencyCode(),
[
'precision' => 2,
'convert' => true,
'currencyFrom' => $data->currencyCode,
'currencyTo' => AppHelper::getUserCurrencyCode(),
]));
},
'format' => 'raw',
],
// ...
],
]); ?>
and in Part.php (Part model) I added method
public static function requestPrice($price)
{
if (strpos($price, 'class') !== false || empty($price) || floatval($price) == 0)
return '<span class="not-set">' . Yii::t('app', 'na vyžiadanie') . '</span>';
else
return $price;
}

Store an array of elements to database (Laravel)

I need advice how to store an array to database. For example i have an input with name="user_phone[]" and i want to store to database the value of this input.
I have a form like so, also there other inputs but i copy just one:
{!! Form::open([route('some.router')]) !!}
<fieldset class="form-group">
{{ Form::label(null, 'Phone') }}
{{ Form::text('user_phone[]', null, ['class' => 'form-control'] ) }}
</fieldset>
{!! Form::close() !!}
and the controller:
public function postAddOrder(Request $request)
{
$this->validate($request, [
'receipt_date' => 'date|required',
'return_date' => 'date|required',
'user_name' => 'required',
'user_phone' => 'required',
'work_sum' => 'integer|required',
'user_descr' => 'required',
'foruser_descr' => 'required'
]);
$user = new User;
$user = $user->all()->find($request->input('user_name'));
$order = new Order([
'receipt_date' => $request->input('receipt_date'),
'return_date' => $request->input('return_date'),
'user_name' => $user->fio,
'user_phone' => $request->input('user_phone'),
'device' => $request->input('device'),
'work_sum' => $request->input('work_sum'),
'master_name' => $request->input('master_name'),
'user_descr' => $request->input('user_descr'),
'foruser_descr' => $request->input('foruser_descr'),
'type' => $request->input('type'),
'status' => $request->input('status'),
'engineer' => $request->input('engineer'),
'partner' => $request->input('partner'),
'office' => $request->input('office')
]);
$order->save();
return redirect()->route('admin.orders.index');
}
The problem is when i'm submitting the form and getting the error:
htmlentities() expects parameter 1 to be string, array given
Also i'm using casts to store an array to DB:
/**
* The attributes that should be casted to native types.
*
* #var array
*/
protected $casts = [
'user_phone' => 'array',
];
The values are storing correctly, the main problem is that the validate() method is not catching the errors. For example im not filling some data in inputs which are required. When instead of getting the error like something is required im getting error
htmlentities() expects parameter 1 to be string, array given
When im filling all input with data everything goes ok.
I think the problem comes from your rule
'user_phone' => 'required
To validate array values you should use the array validation. (Link)
rewrite your rule like so
"user_phone.0" => "required"
this will ensure that at least one user_phone is provided.
In case you wanna validate phone format just go with:
"user_phone.*" => "{Insert validation here}"
Found the definition.
{!! Form::open([route('some.router')]) !!}
<fieldset class="form-group">
{{ Form::label(null, 'Phone') }}
{{ Form::text('user_phone[0]', null, ['class' => 'form-control'] ) }}
</fieldset>
{!! Form::close() !!}
We must pass the index in inputs. Like name="user_phone[0]" after that we are not getting the error:
htmlentities() expects parameter 1 to be string, array given
And validate() method catching the errors. It was the only solution for me.

Categories