Multiple Input เป็นการเพิ่ม Input ในลักษณะ เรียกใช้งาน JavaScript เพื่อเพิ่มช่องสำหรับกรอกข้อมูล เหมาะสำหรับการบันทึกข้อมูลในลักษณะ Master Detail เช่น ใบสั่งซื้อ กับรายการสินค้าที่สั่งซื้อ โดยที่ ใบสั่งซื้อ 1 ใบ มีรายการสินค้าได้หลายชิ้น นั่นเอง
จากตัวอย่างนี้เราจะใช้ Package เสริมสำหรับ Yii2 คือ
https://packagist.org/packages/unclead/yii2-multiple-input
ให้ทำการติดตั้งโดยพิมพ์คำสั่ง
composer require unclead/yii2-multiple-input
ตารางและ Model
ในตัวอย่างนี้ใช้ตาราง order และใช้ Model ชื่อ Order และตาราง order_detail และใช้ Model ชื่อ OrderDetail
จากนั้นทำการตั้งค่าต่างๆ ดังนี้
กำหนด Attribute ใน Model
ให้กำหนด Attribute เพิ่มเติมใน Model เพื่อที่จะรับข้อมูล ตัวอย่างนี้จะใช้ชื่อว่า $items;
class Order extends ActiveRecord
{
public $items;
//...
}
เขียนโปรแกรมส่วน Controller
เขียนโปรแกรมในส่วน Controller โดยนำ array $items ซึ่งเป็นข้อมูลจาก multiple input มา loop เพื่อบันทึกข้อมูล ดังนี้
public function actionCreate()
{
$model = new Order(); //สร้างใบ Order
if($model->load(Yii::$app->request->post()))
{
$transaction = Yii::$app->db->beginTransaction();
try {
$model->save(); //บันทึกใบ Order
$items = Yii::$app->request->post();
//var_dump($items['Order']['items']);
foreach($items['Order']['items'] as $key => $val){ //นำรายการสินค้าที่เลือกมา loop บันทึก
if(empty($val['id'])){
$order_detail = new OrderDetail();
}else{
$order_detail = OrderDetail::findOne($val['id']);
}
$order_detail->order_id = $model->id;
$order_detail->amount = $val['amount'];
//หาราคาสินค้า
$product = Product::findOne($val['product_id']);
$order_detail->product_id = $product->id;
$order_detail->price = $product->price; //ราคาจากสินค้า
$order_detail->save();
}
$transaction->commit();
Yii::$app->session->setFlash('success', 'บันทึกข้อมูลเรียบร้อย');
return $this->redirect(['index']);
} catch (Exception $e) {
$transaction->rollBack();
Yii::$app->session->setFlash('error', 'มีข้อผิดพลาดในการบันทึก');
return $this->redirect(['index']);
}
}
return $this->render('create', [
'model' => $model,
]);
}
public function actionUpdate($id)
{
$model = Order::findOne($id); //เลือกใบ Order
$model->items = OrderDetail::find()->where(['order_id' => $model->id])->all();
if($model->load(Yii::$app->request->post()))
{
$transaction = Yii::$app->db->beginTransaction();
try {
$model->save(); //บันทึกใบ Order
$items = Yii::$app->request->post();
//var_dump($items['Order']['items']);
foreach($items['Order']['items'] as $key => $val){ //นำรายการสินค้าที่เลือกมา loop บันทึก
if(empty($val['id'])){
$order_detail = new OrderDetail();
}else{
$order_detail = OrderDetail::findOne($val['id']);
}
$order_detail->order_id = $model->id;
$order_detail->amount = $val['amount'];
//หาราคาสินค้า
$product = Product::findOne($val['product_id']);
$order_detail->product_id = $product->id;
$order_detail->price = $product->price; //ราคาจากสินค้า
$order_detail->save();
}
$transaction->commit();
Yii::$app->session->setFlash('success', 'บันทึกข้อมูลเรียบร้อย');
return $this->redirect(['index']);
} catch (Exception $e) {
$transaction->rollBack();
Yii::$app->session->setFlash('error', 'มีข้อผิดพลาดในการบันทึก');
return $this->redirect(['index']);
}
}
return $this->render('update', [
'model' => $model,
]);
}
กำหนดการแสดงผลใน View
กำหนดการแสดงผลใน Form ดังนี้
use unclead\widgets\MultipleInput;
use unclead\widgets\MultipleInputColumn;
//ส่วนรายการใบ Order
//...
//ส่วนรายละเอียดการสั่งซื้อ
<?=$form->field($model, 'items')->label(false)->widget(MultipleInput::className(),[
'limit' => 10,// สูงสุด 10 รายการ
'allowEmptyList' => false,
'min' => 1,//อย่างน้อยมี 1 รายการ
'id' => Html::getInputId($model, 'items'),
'columns' => [
[
'name' => 'id',
'title' => 'ID',
'enableError' => true,
'type' => MultipleInputColumn::TYPE_HIDDEN_INPUT,
],
[
'name' => 'product_id',
'title' => 'Name',
'type' => MultipleInputColumn::TYPE_DROPDOWN,
'value' => function($data){
return $data['product_id'];
},
'items' => ArrayHelper::map(Product::find()->orderBy(['name' => SORT_ASC])->all(), 'id', function($model){return $model->code.'-'.$model->name;}),
'enableError' => true,
'options' => [
'class' => 'new_class' ,
'prompt' => 'เลือกสินค้า',
'onchange' => '$(this).init_change();' //ส่งค่าไปเรียก Ajax
]
],
[
'name' => 'product_name',
'type' => MultipleInputColumn::TYPE_STATIC,
'title' => 'Code',
'value' => function($data){
return $data['charge']['code'];
},
'enableError' => true,
],
[
'name' => 'price',
'type' => MultipleInputColumn::TYPE_STATIC,
'title' => 'Price',
'value' => function($data){
return number_format($data['price'],2);
},
'enableError' => true,
],
[
'name' => 'amount',
'title' => 'Amount',
'enableError' => true,
'type' => MultipleInputColumn::TYPE_TEXT_INPUT,
'value' => function($data){
return $data['amount'];
},
],
]
])?>
เขียนคำสั่ง JavaScript ในการแสดงข้อมูล
เขียนคำสั่ง JavaScript ในการแสดงข้อมูลชื่อสินค้า และราคาสินค้า
<?php $this->registerJs('
$.fn.init_change = function(){
var product_id = $(this).val();
$.get(
"'.Url::toRoute('/site/product-detail').'",
{
id: product_id
},
function (data)
{
var result = data.split("-");
$(".field-'.Html::getInputId($model, 'items').'-"+sid[2]+"-product_name").text(result[0]);
$(".field-'.Html::getInputId($model, 'items').'-"+sid[2]+"-price").text(result[1]);
}
);
};
')?>
เพิ่ม Action ProductDetail()
เพิ่ม Action ProductDetail() ใน SiteController
public function actionProductDetail($id = null)
{
$product = Product::findOne($id);
echo $product->name . '-' .$product->price;
}
ตัวอย่างการลบโดยใช้ AJAX
<?php $this->registerJs("
$('#".Html::getInputId($model, 'items')."').on('afterInit', function(){
//console.log('calls on after initialization event');
}).on('beforeAddRow', function(e) {
//console.log('calls on before add row event');
}).on('afterAddRow', function(e) {
//console.log('calls on after add row event');
}).on('beforeDeleteRow', function(e, item){
//console.log(item);
return confirm('คุณแน่ใจนะว่าต้องการลบ?');
}).on('afterDeleteRow', function(e, item){
//console.log(item);
var id_case = item.find('.list-cell__block_no').find('input[id*=\"".Html::getInputId($model, 'items')."-\"]').val();
var from_id = item.find('.list-cell__block_no').find('input[id*=\"".Html::getInputId($model, 'items')."-\"][id$=\"-from_id\"]').val();
var im_id = item.find('.list-cell__block_no').find('input[id*=\"".Html::getInputId($model, 'items')."-\"][id$=\"-id\"]').val();
//alert(id_case + from_id);
$.post(\"".Url::to(['/immuno/staining/finance-service-charge-delete'])."\",
{
id_case: id_case,
from_id: from_id,
im_id: im_id
},
function(data, status){
//alert(\"Data: \" + data); // + \"Status: \" + status
}
);
});
")?>
ความคิดเห็น