资讯专栏INFORMATION COLUMN

Yii2 插件系列——kartikdetailDetailView

graf / 3617人阅读

摘要:视图用属性属性放这关闭动画的数组格式如下提交时间测试姓名昵称联系人分类男性别注意如果编辑与保存刷新的页面分开写,那么记得也要在刷新的页面加上属性,不然保存刷新后加上的自定义字段就消失了。

前言

前段时间研究了DetailView插件结合自定义字段的显示与编辑,DetailView插件本身没有这么灵活,要实现这种效果必须得改造插件。显示与编辑DetailView插件都有了,只需要我们把自定义的字段加进去就行可以实现了。但是怎么加进去呢?既然是自定义字段,那肯定是可有可无,不能写死的,我来分享下具体实现思路吧!

效果图

提交时间、昵称、联系人分类、性别属于自定义字段

找插件源码

找插件的源码(vendorkartik-vyii2-detail-viewDetailView.php),可以通过它方法的命名或者打印测试找到相关的代码,知点击详细时走插件的如下方法:

</>复制代码

  1. /**
  2. * Renders the main detail view widget
  3. *
  4. * @return string the detail view content
  5. */
  6. protected function renderDetailView()
  7. {
  8. $rows = [];
  9. foreach ($this->attributes as $attribute) {
  10. $rows[] = $this->renderAttributeRow($attribute);
  11. }
  12. $tag = ArrayHelper::remove($this->options, "tag", "table");
  13. $output = Html::tag($tag, implode("
  14. ", $rows), $this->options);
  15. return ($this->bootstrap && $this->responsive) ?
  16. "
    " . $output . "
    " :
  17. "
    " . $output . "
    ";
  18. }
重写类及其方法

1、类与方法都找到了,就重写。把DetailView类以及renderDetailView方法里涉及的方法、组件都拷贝过来重写一遍,并继承父类kartikdetailDetailView。

2、仿造父类的public $attributes;属性给子类增加public $custom;属性,原因是$attributes属性的字段与自定义字段走的不是同一个model,所以必须得定义一个新的属性来用。

3、重写完了之后代码如下(重点注意的部分我在代码中已加上注释):

</>复制代码

  1. "hiddenInput",
  2. self::INPUT_TEXT => "textInput",
  3. self::INPUT_PASSWORD => "passwordInput",
  4. self::INPUT_TEXTAREA => "textArea",
  5. self::INPUT_CHECKBOX => "checkbox",
  6. self::INPUT_RADIO => "radio",
  7. self::INPUT_LIST_BOX => "listBox",
  8. self::INPUT_DROPDOWN_LIST => "dropDownList",
  9. self::INPUT_CHECKBOX_LIST => "checkboxList",
  10. self::INPUT_RADIO_LIST => "radioList",
  11. self::INPUT_HTML5_INPUT => "input",
  12. self::INPUT_FILE => "fileInput",
  13. self::INPUT_WIDGET => "widget",
  14. ];
  15. // dropdown inputs
  16. private static $_dropDownInputs = [
  17. self::INPUT_LIST_BOX => "listBox",
  18. self::INPUT_DROPDOWN_LIST => "dropDownList",
  19. self::INPUT_CHECKBOX_LIST => "checkboxList",
  20. self::INPUT_RADIO_LIST => "radioList",
  21. ];
  22. protected function renderDetailView()
  23. {
  24. $rows = [];
  25. foreach ($this->attributes as $attribute) {
  26. $rows[] = $this->renderAttributeRow($attribute);
  27. }
  28. //注意点一:增加循环获取自定义字段的值
  29. foreach ($this->custom["attributes"] as $attribute) {
  30. $rows[] = $this->renderCustomAttributeRow($attribute);
  31. }
  32. $tag = ArrayHelper::remove($this->options, "tag", "table");
  33. $output = Html::tag($tag, implode("
  34. ", $rows), $this->options);
  35. return ($this->bootstrap && $this->responsive) ?
  36. "
    " . $output . "
    " :
  37. "
    " . $output . "
    ";
  38. }
  39. //自定义字段的显示
  40. protected function renderCustomAttributeRow($attribute)
  41. {
  42. //注意点二:只留这三行代码,把其它多余的删除
  43. $this->_rowOptions = ArrayHelper::getValue($attribute, "rowOptions", $this->rowOptions);
  44. $content = $this->renderCustomAttributeItem($attribute);
  45. return Html::tag("tr", $content, $this->_rowOptions);
  46. }
  47. protected function renderCustomAttributeItem($attribute)
  48. {
  49. $labelColOpts = ArrayHelper::getValue($attribute, "labelColOptions", $this->labelColOptions);
  50. $valueColOpts = ArrayHelper::getValue($attribute, "valueColOptions", $this->valueColOptions);
  51. if (ArrayHelper::getValue($attribute, "group", false)) {
  52. $groupOptions = ArrayHelper::getValue($attribute, "groupOptions", []);
  53. $label = ArrayHelper::getValue($attribute, "label", "");
  54. if (empty($groupOptions["colspan"])) {
  55. $groupOptions["colspan"] = 2;
  56. }
  57. return Html::tag("th", $label, $groupOptions);
  58. }
  59. if ($this->hideIfEmpty === true && empty($attribute["value"])) {
  60. Html::addCssClass($this->_rowOptions, "kv-view-hidden");
  61. }
  62. if (ArrayHelper::getValue($attribute, "type", "text") === self::INPUT_HIDDEN) {
  63. Html::addCssClass($this->_rowOptions, "kv-edit-hidden");
  64. }
  65. $value = $attribute["value"];
  66. if ($this->notSetIfEmpty && ($value === "" || $value === null)) {
  67. $value = null;
  68. }
  69. $dispAttr = $this->formatter->format($value, $attribute["format"]);
  70. Html::addCssClass($this->viewAttributeContainer, "kv-attribute");
  71. Html::addCssClass($this->editAttributeContainer, "kv-form-attribute");
  72. $output = Html::tag("div", $dispAttr, $this->viewAttributeContainer) . "
  73. ";
  74. //var_dump($this->editAttributeContainer);exit;
  75. if ($this->enableEditMode) {
  76. $editInput = ArrayHelper::getValue($attribute, "displayOnly", false) ? $dispAttr : $this->renderFormCustomAttribute($attribute);
  77. $output .= Html::tag("div", $editInput, $this->editAttributeContainer);
  78. }
  79. return Html::tag("th", $attribute["label"], $labelColOpts) . "
  80. " . Html::tag("td", $output, $valueColOpts);
  81. }
  82. protected function renderFormCustomAttribute($config)
  83. {
  84. if (empty($config["attribute"])) {
  85. return "";
  86. }
  87. //注意点三:把这里的model注释掉,不能用,这是attribute的model
  88. //$model = ArrayHelper::getValue($config, "editModel", $this->model);
  89. //if (!$model instanceof Model) {
  90. $model = $this->model;
  91. //}
  92. $attr = ArrayHelper::getValue($config, "updateAttr", $config["attribute"]);
  93. $input = ArrayHelper::getValue($config, "type", self::INPUT_TEXT);
  94. $fieldConfig = ArrayHelper::getValue($config, "fieldConfig", []);
  95. $inputWidth = ArrayHelper::getValue($config, "inputWidth", "");
  96. $container = ArrayHelper::getValue($config, "inputContainer", []);
  97. if ($inputWidth != "") {
  98. Html::addCssStyle($container, "width: {$inputWidth}"); // deprecated since v1.7.4
  99. }
  100. $template = ArrayHelper::getValue($fieldConfig, "template", "{input}
  101. {error}
  102. {hint}");
  103. $row = Html::tag("div", $template, $container);
  104. if (static::hasGridCol($container)) {
  105. $row = "
    " . $row . "
    ";
  106. }
  107. $fieldConfig["template"] = $row;
  108. if (substr($input, 0, 8) == "kartik") {
  109. Config::validateInputWidget($input, "as an input widget for DetailView edit mode");
  110. } elseif ($input !== self::INPUT_WIDGET && !in_array($input, self::$_inputsList)) {
  111. throw new InvalidConfigException(
  112. "Invalid input type "{$input}" defined for the attribute "" . $config["attribute"] . ""."
  113. );
  114. }
  115. $options = ArrayHelper::getValue($config, "options", []);
  116. $widgetOptions = ArrayHelper::getValue($config, "widgetOptions", []);
  117. $class = ArrayHelper::remove($widgetOptions, "class", "");
  118. if (!empty($config["options"])) {
  119. $widgetOptions["options"] = $config["options"];
  120. }
  121. //return array("options"=> array("class"=> "form-group"));
  122. //return "yyyy";
  123. if (Config::isInputWidget($input)) {
  124. $class = $input;
  125. return $this->_form->field($model, $attr, $fieldConfig)->widget($class, $widgetOptions);
  126. }
  127. if ($input === self::INPUT_WIDGET) {
  128. if ($class == "") {
  129. throw new InvalidConfigException("Widget class not defined in "widgetOptions" for {$input}".");
  130. }
  131. return $this->_form->field($model, $attr, $fieldConfig)->widget($class, $widgetOptions);
  132. }
  133. if (in_array($input, self::$_dropDownInputs)) {
  134. $items = ArrayHelper::getValue($config, "items", []);
  135. return $this->_form->field($model, $attr, $fieldConfig)->$input($items, $options);
  136. }
  137. if ($input == self::INPUT_HTML5_INPUT) {
  138. $inputType = ArrayHelper::getValue($config, "inputType", self::INPUT_TEXT);
  139. return $this->_form->field($model, $attr, $fieldConfig)->$input($inputType, $options);
  140. }
  141. /*
  142. 注意点四:把原来的返回值改写。至于为什么要改写成如下,原因有:
  143. 1、用$this->_form->field()的话会走attribute的model,改写失败;
  144. 2、可以参照$this->_form->field()的用法,然后查看原码生成功div、input的规律你就明白为什么要这么改写了。
  145. */
  146. $name = $this->custom["id"]."[".$config["attribute"]."]";
  147. $id = strtolower($this->custom["id"])."-".$config["attribute"];
  148. $html = Html::input("text", $name, $config["value"], ["class" => "form-control","id"=> $id]);
  149. $html .= Html::tag("div", "", ["class" => "help-block"]);
  150. $html = Html::tag("div", $html, []);
  151. $fieldclass = "field-".$id;
  152. $html = Html::tag("div", $html, ["class" => $fieldclass]);
  153. return $html;
  154. }
  155. }
视图用custom属性

</>复制代码

  1. "contact-view",
  2. "formOptions"=>[
  3. "id"=>"contact-form-view",
  4. "action"=>"/contact/update?id=".$model->id."&salesId=".$model->sale_id,
  5. "options"=>["data-form"=>"public-form-submit"],
  6. ],
  7. "model" => $model,
  8. "condensed"=>false,
  9. "hover"=>true,
  10. "mode"=>Yii::$app->request->get("edit")=="t" ? DetailView::MODE_EDIT : DetailView::MODE_VIEW,
  11. "panel"=>[
  12. "heading"=>$this->title,
  13. "type"=>DetailView::TYPE_INFO,
  14. ],
  15. "custom" => $custom, //custom属性放这
  16. "attributes" => $attributes,
  17. "deleteOptions"=>[
  18. "class"=>"prohibit deletet",
  19. "label"=>"",
  20. ],
  21. "enableEditMode"=>true,
  22. "fadeDelay"=>0, //关闭动画
  23. ]) ?>

$custom的数组格式如下:

</>复制代码

  1. Array
  2. (
  3. [id] => ClassForm
  4. [attributes] => Array
  5. (
  6. [0] => Array
  7. (
  8. [attribute] => add_time
  9. [value] =>
  10. [label] => 提交时间
  11. [format] => text
  12. )
  13. [1] => Array
  14. (
  15. [attribute] => nickname
  16. [value] => 测试姓名
  17. [label] => 昵称
  18. [format] => text
  19. )
  20. [2] => Array
  21. (
  22. [attribute] => sort
  23. [value] =>
  24. [label] => 联系人分类
  25. [format] => text
  26. )
  27. [3] => Array
  28. (
  29. [attribute] => sex
  30. [value] => 男
  31. [label] => 性别
  32. [format] => text
  33. )
  34. )
  35. )

注意:如果编辑与保存刷新的页面分开写,那么记得也要在刷新的页面加上custom属性,不然保存刷新后加上的自定义字段就消失了。

总结分析

以上就是我要给大家分享的DetailView插件结合自定义字段的显示与编辑的实现过程。
搞程序,水很深,不常总结,将来更费劲。
(完)

相关资料

1、DetailView

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82104.html

相关文章

  • Yii2 插件系列——kartikdetailDetailView

    摘要:视图用属性属性放这关闭动画的数组格式如下提交时间测试姓名昵称联系人分类男性别注意如果编辑与保存刷新的页面分开写,那么记得也要在刷新的页面加上属性,不然保存刷新后加上的自定义字段就消失了。 前言 前段时间研究了DetailView插件结合自定义字段的显示与编辑,DetailView插件本身没有这么灵活,要实现这种效果必须得改造插件。显示与编辑DetailView插件都有了,只需要我们把自...

    lieeps 评论0 收藏0
  • Yii2系列教程六:集成编辑器

    摘要:而这些问题目前的最好解决方案就是集成一个编辑器,鉴于大家这里不是指程序员都是喜欢所见即所得,所以,这里我主要是演示怎么集成所见即所得的富文本编辑器。 原文来自: https://jellybool.com/post/programming-with-yii2-rich-text-input-with-redactor 首先,很惭愧的是,前几天都出去外面玩了,没有及时更新教程,...

    xiaochao 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<