永久內嵌核取方塊
Editor 使用的主要互動方法是其主要燈箱輸入表單、泡泡編輯器或內嵌編輯,但也可以透過其 廣泛的 API 建構您自己的表單控制項來使用 Editor。
我最近被問到是否有可能在表格中永久顯示核取方塊,以顯示布林值欄位的狀態,並在單擊切換時更新該欄位。使用 Editor 的 內嵌編輯選項,可以透過單擊在表格中插入核取方塊,並呼叫 inline()
方法,但是需要再次單擊才能變更值並提交表單。雖然快速,但是當您擁有布林值狀態切換很常見的資料時,單擊更新可以改善應用程式的互動性。
在這篇文章中,我將展示如何使用 Editor 的 API,透過建構具有核取方塊列的表格來觸發資料更新,並在切換時立即寫入資料庫。此外,整列 (包括布林值狀態) 將透過標準 Editor 編輯選項保持可編輯狀態。
如果您很想跳到最後並查看完成的產品,可以在 Editor 範例網站上實際執行查看這篇文章中開發的程式碼。
起點
對於這篇文章中建立的應用範例,我將使用 Editor 套件附帶的其中一個範例資料庫表格,因為它非常適合此使用案例。具體來說,users
表格有一個二進位 active
欄位,我們可以將其用於我們的核取方塊清單。
作為這篇文章的起點,請考慮以下 Editor 和 DataTables 初始化(請注意,如果您是 DataTables 和 Editor 的新手,它們各自的手冊 DataTables / Editor 都有關於如何設定和配置這兩個程式庫的詳細資訊)
Javascript
var editor = new $.fn.dataTable.Editor( {
"ajax": "../php/checkbox.php",
"table": "#example",
"fields": [
{
label: "Active:",
name: "active",
type: "checkbox",
separator: "|",
ipOpts: [
{ label: '', value: 1 }
]
},
{ label: "First name:", name: "first_name" },
{ label: "Last name:", name: "last_name" },
{ label: "Phone:", name: "phone" },
{ label: "City:", name: "city" },
{ label: "Zip:", name: "zip" }
]
} );
$('#example').dataTable( {
dom: "Tfrtip",
ajax: "../php/checkbox.php",
columns: [
{ data: "first_name" },
{ data: "last_name" },
{ data: "phone" },
{ data: "city" },
{ data: "zip" },
{ data: "active" }
],
tableTools: {
sRowSelect: "os",
aButtons: [
{ sExtends: "editor_create", editor: editor },
{ sExtends: "editor_edit", editor: editor },
{ sExtends: "editor_remove", editor: editor }
]
}
} );
PHP
include( "DataTables.php" );
use
DataTables\Editor,
DataTables\Editor\Field,
DataTables\Editor\Format,
DataTables\Editor\Join,
DataTables\Editor\Validate;
Editor::inst( $db, 'users' )
->fields(
Field::inst( 'first_name' ),
Field::inst( 'last_name' ),
Field::inst( 'phone' ),
Field::inst( 'city' ),
Field::inst( 'zip' ),
Field::inst( 'active' )
->setFormatter( function ( $val, $data, $opts ) {
return ! $val ? 0 : 1;
} )
)
->process( $_POST )
->json();
您可以從上面的程式碼中注意到,表格中有六個欄位,而且每個欄位都可以在 Editor 中編輯。active
欄位是 checkbox
類型,我們使用 separator
選項讓 Editor 將資料作為字串提交,而不是像預設那樣作為陣列提交(適用於有多個核取方塊的情況)。
在 PHP 中,唯一需要特別考慮的是取消選取核取方塊的情況。當核取方塊未被選取時,瀏覽器不會提交值,因此我們使用 setFormatter
來確保使用 0
或 1
作為資料庫看到的值(請參閱 Editor PHP 手冊)。
上面的程式碼將會成功執行,而且我們的表格是完全可編輯的,但是現在讓我們來看看如何將永久核取方塊新增到表格中。
顯示輸入核取方塊
在沒有任何資料渲染器(如上面的情況)的情況下,從資料庫讀取的資訊會直接寫入表格,因此也就是使用者將看到的內容。在 active
欄位的情況下,這將是 0
或 1
,但是我們想要顯示核取方塊。為了實現這一點,我們可以使用 DataTables 的欄位渲染選項:columns.render
。具體來說,我們想要檢查 display
資料類型並傳回 HTML 核取方塊。對於其他資料類型(例如 sort
),我們傳回原始資料(請參閱 正交資料 以取得更多資訊)。這可確保該欄位仍然可以排序和搜尋。
{
data: "active",
render: function ( data, type, row ) {
if ( type === 'display' ) {
return '<input type="checkbox" class="editor-active">';
}
return data;
},
className: "dt-body-center"
}
請注意,columns.className
選項也用於指定 dt-body-center
類別,該類別內建於 DataTables 預設樣式表中,以便將核取方塊在欄位中置中對齊 - 如需更多有關內建樣式選項的資訊,請參閱樣式手冊。
接下來,我們需要設定核取方塊的選取狀態。為了確保這始終與該列的來源資料保持同步(例如,如果在 Editor 燈箱表單中變更了狀態),則使用 rowCallback
選項。這是一個回呼函式,對於 DataTables 顯示的每一列都會執行,因此我們可以使用簡單的 jQuery 行來設定 checked
屬性
rowCallback: function ( row, data ) {
// Set the checked state of the checkbox in the table
$('input.editor-active', row).prop( 'checked', data.active == 1 );
}
最後,對於表格顯示,我們需要認識到 TableTools 列選取器預設會在單擊列的任何部分(包括核取方塊等子元素)時選取列。單擊核取方塊是一種理想的操作,但是我們不希望因此而選取列。雖然可以使用 stopPropagation()
和事件監聽器,但是 TableTools 提供了一種更簡單的方法 - sRowSelector
選項。
此屬性提供了告訴 TableTools 使用哪個選取器來進行列選取的功能。在這種情況下,我們想要使用整列,除了最後一欄。為此,我們可以使用簡單的 CSS 選取器(請注意,這會新增到 tableTools
初始化物件中)
sRowSelector: 'td:not(:last-child)' // no row selection on last column
API 更新
顯示核取方塊後,此程序的下一步也是最後一步是在狀態變更時執行 Editor 動作。為此,我們使用 jQuery change
事件處理常式來呼叫 edit()
方法來開始編輯該列。使用 edit()
的第二個參數,我們可以告知表單不要顯示(預設情況下會顯示)。
然後,使用 set()
方法,根據切換的核取方塊設定 active
狀態的值,最後使用 submit()
方法將資料提交到伺服器。
$('#example').on( 'change', 'input.editor-active', function () {
editor
.edit( $(this).closest('tr'), false )
.set( 'active', $(this).prop( 'checked' ) ? 1 : 0 )
.submit();
} );
就是這樣!
執行範例
此範例可在 Editor 網站上取得,您可以在其中使用這篇文章中開發的程式碼,並在有興趣的情況下進一步解構它。
完整程式碼
為了完整起見,上述討論的程式碼會與這篇文章頂部的起點合併,以顯示完全組裝的完整工作程式碼
var editor = new $.fn.dataTable.Editor( {
"ajax": "../php/checkbox.php",
"table": "#example",
"fields": [ {
label: "Active:",
name: "active",
type: "checkbox",
separator: "|",
ipOpts: [
{ label: '', value: 1 }
]
},
{ label: "First name:", name: "first_name" },
{ label: "Last name:", name: "last_name" },
{ label: "Phone:", name: "phone" },
{ label: "City:", name: "city" },
{ label: "Zip:", name: "zip" }
]
} );
$('#example').dataTable( {
dom: "Tfrtip",
ajax: "../php/checkbox.php",
columns: [
{ data: "first_name" },
{ data: "last_name" },
{ data: "phone" },
{ data: "city" },
{ data: "zip" },
{
data: "active",
render: function ( data, type, row ) {
if ( type === 'display' ) {
return '<input type="checkbox" class="editor-active">';
}
return data;
},
className: "dt-body-center"
}
],
tableTools: {
sRowSelect: "os",
aButtons: [
{ sExtends: "editor_create", editor: editor },
{ sExtends: "editor_edit", editor: editor },
{ sExtends: "editor_remove", editor: editor }
],
sRowSelector: 'td:not(:last-child)' // no row selection on last column
},
rowCallback: function ( row, data ) {
// Set the checked state of the checkbox in the table
$('input.editor-active', row).prop( 'checked', data.active == 1 );
}
} );
$('#example').on( 'change', 'input.editor-active', function () {
editor
.edit( $(this).closest('tr'), false )
.set( 'active', $(this).prop( 'checked' ) ? 1 : 0 )
.submit();
} );