2015-04-21 39 views
0

我有一个包含CSV字符串的属性的模型。Yii2:如何将属性中的CSV字符串映射到表单中的CheckboxList?

(该模型实际上是一个ActiveRecord的对象,但我想这并不重要。纠正我,如果我错了。)

/** 
* @property string $colors Can be something like "red" or "red,green,blue" or "" 
*/ 
class Product extends Model {   
} 

而且我有,我想这显示一种形式属性作为checkboxList,以便用户可以通过简单的点击来选择可能的值,而不是键入到textInput中。

从理论上讲,它应该与此类似:

<?php $availableColors = ['red' => 'Red', 'green' => 'Green', 'blue' => 'Blue']; ?> 

<?php $form = ActiveForm::begin([]); ?> 
    <?= $form->field($model, 'colors')->checkboxList($availableColors) ?> 
<?php ActiveForm::end(); ?> 

但这显然是不行的,因为该领域colors将需要一个数组。但在我的模型中,它是一个字符串。

什么是实现该目标的好方法?用JS或伪属性? colors属性不能更改,因为它已经在不应该被修改的其他上下文中使用。

回答

0

现在我解决了它与表单的额外模型。这在我看来是一个合适的解决方案。

/** 
* @property string $colors Can be something like "red" or "red,green,blue" or "" 
*/ 
class Product extends Model { 
} 

/** 
* @property string[] $colorsAsArray 
*/ 
class ProductForm extends Product { 

    public function rules() { 
     return array_merge(parent::rules(), [ 
      ['colorsAsArray', 'safe'] // just to make it possible to use load() 
     ]); 
    } 

    public function getColorsAsArray() { 
     return explode(',', $this->colors); 
    } 

    public function setColorsAsArray($value) { 
     $this->colors = self::implode($value); 
    } 

    protected static function implode($value) { 
     if ($value == 'none-value') return ''; 
     return implode(',', $value); 
    } 

    /* - - - - - - - - - - optional - - - - - - - - - - */ 

    public function attributeLabels() { 
     $attributeLabels = parent::attributeLabels(); 
     return array_merge($attributeLabels, [ 
      'colorsAsArray' => $attributeLabels['colors'], 
     ]); 
    } 
} 

有了这个,我可以使用的形式方式:

<?php $availableColors = ['red' => 'Red', 'green' => 'Green', 'blue' => 'Blue']; ?> 

<?php $form = ActiveForm::begin([]); ?> 
    <?= $form->field($model, 'colorsAsArray') 
      ->checkboxList($availableColors, ['unselect' => 'none-value']) ?> 
<?php ActiveForm::end(); ?> 

当然,现在控制器必须使用继承的模型类。

如果未选中复选框,该解决方案还处理该问题。这就是为什么'none-value'被引入。

0

我认为这是一个PHP的问题,但无论如何,你可以使用PHP爆炸来构建你需要的数组。有关更多详细信息,请参阅here,然后用户使用复选框列表中的数组。列表

+0

我知道爆炸。但还有更多的事情要做。 – robsch

+0

您可以在模型中添加一个字段,您可以在其中输入数组形式的字符串“colors”的值,并且当用户执行提交时,可以根据从这些数组读取的值重建字符串。 – scaisEdge

0

CSV是一种文件格式,用于在本机操作不兼容格式的程序之间移动表格数据。用它作为模型属性并不是很优雅(说得很好)。在我看来,你应该已经开始将你的颜色存储在一个数组中。

这就是说,你可以达到使用模型中的beforeValidate()功能从下拉列表转换阵列数据CSV:

public function beforeValidate() { 
    $this->colors = explode(';', $this->colors); 

    return parent::beforeValidate(); 
} 
1

您可以在模型覆盖beforeValidate方法,以implode你的颜色数组串。在您看来,您可以使用以下内容:

<?= $form->field($model, 'colors')->checkboxList($availableColors, 
     [ 
      'item'=> function ($index, $label, $name, $checked, $value) use ($model) { 
       $colors = explode(';', $model->colors); 
       $checked = in_array($value, $colors); 
       return Html::checkbox($name, $checked, [ 
        'value' => $value, 
        'label' => $label, 
       ]); 
      } 
     ]) ?> 
相关问题