synatree/yii2-dynamic-relations

允许Yii2视图包含基于模型关系的动态扩展字段集。

安装: 2,760

依赖: 0

建议者: 0

安全: 0

星标: 12

关注者: 5

分支: 15

开放问题: 3

类型:yii2-extension

dev-master 2015-12-21 02:15 UTC

This package is not auto-updated.

Last update: 2024-09-28 16:41:28 UTC


README

这个扩展是在我徒劳地搜索像这样的东西之后出现的:

  • 动态从“主”视图创建“子”模型
  • 动态添加到Yii2视图的输入
  • 在相关模型中使用Yii2小部件
  • 动态向表单添加字段

希望上面的内容能节省其他人一些搜索时间。

这能做什么?

有时候,一张图片胜过千言万语: 基本功能截图

允许Yii2视图包含基于模型关系的动态扩展字段集。

此系统允许您定义一个视图,通常称为_inline.php,当用户点击表单上的“添加”按钮时,该视图将被自动加载。

幕后,模块负责处理保存相关记录(如果它们是新的),更新它们(如果它们已被更改),以及删除它们(如果它们被删除)。

这基本上是通过Ajax添加任意扩展的相关记录集到模型的一种方式。

它还被设计成智能地移动视图小部件可能使用的JavaScript和事件绑定,以避免在通过ajax添加多个“相同”视图时相互冲突。坦白地说,管理由此产生的JavaScript冲突是这里最大的时间节省。

我不确定安全影响实际上有多大,但为了安全起见,我还将代码的ajax请求部分与用户的会话绑定,因此用户会话丢失后重放相同的请求不应该可能。设置方式也基本上隐藏了内联视图的真实名称和路径;我只是不喜欢脚本将服务器端文件路径泄漏到HTML代码中。

安装

安装此扩展的最佳方式是通过composer

运行以下命令之一:

php composer.phar require synatree/yii2-dynamic-relations "dev-master"

或者

"synatree/yii2-dynamic-relations": "dev-master"

将以下内容添加到您的 composer.json 文件的 require 部分。

接下来,您必须将以下内容添加到您的模块配置中:

    'modules' => [
    ...
		'dynamicrelations' => [
			'class' => '\synatree\dynamicrelations\Module'
		],
    ...

用法

您应该做的第一件事是为要动态使用的模型创建一个名为 _inline.php 的视图。此视图可以包含任意小部件,它已与Krajee的一些小部件进行了测试。

这是最复杂的一部分,因为我们必须确保每次调用此视图时,生成的HTML和脚本都是唯一的。

您还必须告诉DynamicRelations如何通过提供路由来添加和删除模型。

最后,您必须保持字段名称的某种结构,以便小部件可以在提交时识别新模型和现有模型。示例

use synatree\dynamicrelations\DynamicRelations;
use kartik\widgets\ActiveForm;
use kartik\datecontrol\DateControl;
use yii\helpers\Url;

/* @var $this yii\web\View */
/* @var $model app\models\BusinessHours */
/* @var $form kartik\widgets\ActiveForm */

// generate something globally unique.
$uniq = uniqid();

if( $model->primaryKey )
{
    // you must define an attribute called "data-dynamic-relation-remove-route" if you plan to allow inline deletion of models from the form.

	$removeAttr = 'data-dynamic-relation-remove-route="' . 
		Url::toRoute(['business-hours/delete', 'id'=>$model->primaryKey]) . '"';
	$frag = "BusinessHours[{$model->primaryKey}]";
}
else
{
    $removeAttr = "";
    // new models must go under a key called "[new]"
    $frag = "BusinessHours[new][$uniq]";
}

?>
<div class="BusinessHours-form form-inline" <?= $removeAttr; ?>>

    <?= DateControl::widget([
			'type' => DateControl::FORMAT_DATE,
			'name' => $frag.'[day]', // expanded, this ends up being something like BusinessHours[1][day] or BusinessHours[new][random][day]
			'value' => $model->day,
			// for Kartik widgets, include the following line.  This basically generates a globally unique set of pluginOptions, which is important to prevent
			// javascript errors and make sure everything works as expected.
			'options' => DynamicRelations::uniqueOptions('day',$uniq)
    ]);?>
    .... More widgets use the same structure as above .... 
</div>

下一步是设置控制器以保存您期望接收的相关模型。在以下示例中,我们只需要在每个创建和更新操作方法中添加一行小代码。

use synatree\dynamicrelations\DynamicRelations;
use app\models\BusinessHours;
use yii\web\Controller;

class SomeController extends Controller
{
    /**
	 * Creates a new SomethingModel model.
	 * If creation is successful, the browser will be redirected to the 'view' page.
	 * @return mixed
    */

    public function actionCreate()
    {
        $model = new SomethingModel();

            if ($model->load(Yii::$app->request->post()) && $model->save()) {
				// this next line is the only one added to a standard Gii-created controller action:
                DynamicRelations::relate($model, 'hours', Yii::$app->request->post(), 'BusinessHours', BusinessHours::className());
                //           Parent Model --^       ^-- Attribute    ^-- Array to search  ^-- Root Key  ^-- Model Class Name
                return $this->redirect(['view', 'id' => $model->primaryKey]);
            } else {
                return $this->render('create', [
                    'model' => $model,
                ]);
            }
    }

    public function actionUpdate($id)
    {
        ...
        if ($model->save()) {
            // this next line exactly the same as in actionCreate:
            DynamicRelations::relate($model, 'hours', Yii::$app->request->post(), 'BusinessHours', BusinessHours::className());
            return $this->redirect(['view', 'id' => $model->boatShowId]);
        } else {
            return $this->render('update', [
                'model' => $model,
            ]);
        }
        ...
    }
}

为了支持Ajax删除相关记录,修改您的相关模型控制器

 /**
     * Deletes an existing BusinessHours model.
     * If deletion is successful, the browser will be redirected to the 'index' page.
     * @param integer $id
     * @return mixed
     */
    public function actionDelete($id)
    {
        $this->findModel($id)->delete();
        if(! Yii::$app->request->isAjax){
                return $this->redirect(['index']);
        }
        else
        {
                return "OK";
        }
    }

最后,在您对父模型的看法中,对于每个您想要动态添加的相关模型,包括以下类似的行。

use synatree\dynamicrelations\DynamicRelations;
<?= DynamicRelations::widget([
	'title' => 'Business Hours',
	'collection' => $model->hours,
	'viewPath' => '@app/views/business-hours/_inline.php',

	// this next line is only needed if there is a chance that the collection above will be empty.  This gives the script a prototype to work with.
	'collectionType' => new \app\models\BusinessHours,

]); ?>

这样应该就完成了。我希望这能帮助到人们,我真的很希望这个功能能实现。