Hi there,
I have a model in my app called Feature which has name and value properties and santed to display an array of that model in the same way a DetailView is. Have drafted a widget for such purpose, but I’m looking for experienced yii2 developer thoughts as have used an existing widget as starting.
This is the code:
<?php
namespace app\common\widgets;
use Yii;
use yii\base\Arrayable;
use yii\i18n\Formatter;
use yii\base\InvalidConfigException;
use yii\base\Model;
use yii\base\Widget;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Inflector;
use yii\helpers\VarDumper;
/**
* Widget for display list of links to related models
*/
class KeyValueListView extends Widget
{
/**
* @var \yii\data\DataProviderInterface the data provider for the view. This property is required.
*/
public $dataProvider;
/**
* @var string|callable the template used to render a single model. If a string, the token `{label}`
* and `{value}` will be replaced with the label and the value of the corresponding model.
* If a callback (e.g. an anonymous function), the signature must be as follows:
*
* ```php
* function ($model, $index, $widget)
* ```
*
* where `$model` refer to the specification of the model being rendered, `$index` is the zero-based
* index of the model in the [[models]] array, and `$widget` refers to this widget instance.
*/
public $template = '<tr><th>{label}</th><td>{value}</td></tr>';
/**
* @var array the HTML attributes for the container tag of this widget. The "tag" option specifies
* what container tag should be used. It defaults to "table" if not set.
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $options = ['class' => 'table table-striped table-bordered detail-view'];
/**
* @var array|Formatter the formatter used to format model attribute values into displayable texts.
* This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]]
* instance. If this property is not set, the "formatter" application component will be used.
*/
public $formatter;
/**
* @var string Property that stands for the label
*/
public $label;
/**
* @var string Property that stands for the value
*/
public $value;
/**
* Initializes the detail view.
* This method will initialize required property values.
*/
public function init()
{
if ($this->dataProvider === null) {
throw new InvalidConfigException('Please specify the "dataProvider" property.');
}
if ($this->label === null) {
throw new InvalidConfigException('Please specify the "label" property.');
}
if ($this->value === null) {
throw new InvalidConfigException('Please specify the "value" property.');
}
if ($this->formatter === null) {
$this->formatter = Yii::$app->getFormatter();
} elseif (is_array($this->formatter)) {
$this->formatter = Yii::createObject($this->formatter);
}
if (!$this->formatter instanceof Formatter) {
throw new InvalidConfigException('The "formatter" property must be either a Format object or a configuration array.');
}
}
/**
* Renders the detail view.
* This is the main entry of the whole detail view rendering.
*/
public function run()
{
$rows = [];
$i = 0;
foreach ($this->dataProvider->getModels() as $model) {
$rows[] = $this->renderModel($model, $i++);
}
$options = $this->options;
$tag = ArrayHelper::remove($options, 'tag', 'table');
echo Html::tag($tag, implode("\n", $rows), $options);
}
/**
* Renders a single model.
* @param array $model the specification of the model to be rendered.
* @param integer $index the zero-based index of the attribute in the [[models]] array
* @return string the rendering result
*/
protected function renderModel($model, $index)
{
if (is_string($this->template)) {
return strtr($this->template, [
'{label}' => ArrayHelper::getValue($model,$this->label),
'{value}' => ArrayHelper::getValue($model ,$this->value),
]);
} else {
return call_user_func($this->template, $model, $index, $this);
}
}
}
and this is how it’s being used:
<?= KeyValueListView::widget([
'dataProvider' => $dataProvider,
'label' => 'feature.name',
'value' => 'value',
]) ?>
This widget is being used in a related viewm that’s why the label is feature.name
Thanks in advance