Adding columns
Add your own fields to the Bulk Editor with the gridline_columns filter: the column format, value types, validation and sorting.
Any product field can become a Bulk Editor column with the gridline_columns filter. Put the code in a small custom plugin or your child theme's functions.php. Columns you add get everything the built-in ones have: keyboard editing, highlighted unsaved changes, errors on their cell, Screen Options, and with Gridline Pro bulk changes, undo and CSV export.
A first column
// A "Gift wrap available" yes/no column, stored in product meta.
add_filter( 'gridline_columns', function ( $columns ) {
$columns['gift_wrap'] = array(
'label' => 'Gift wrap',
'group' => 'Extras',
'type' => 'bool',
'get' => function ( WC_Product $product ) {
return $product->get_meta( '_gift_wrap' ) ? 'yes' : 'no';
},
'set' => function ( WC_Product $product, $value ) {
$product->update_meta_data( '_gift_wrap', 'yes' === $value ? 1 : '' );
},
);
return $columns;
} );
The key (gift_wrap) must be unique. The product is saved by Gridline after set runs, so don't call save() yourself.
The column format
| Key | Required | What it is |
|---|---|---|
label |
yes | Shown in the header and in Screen Options |
type |
yes | How the value is shown and edited (see below) |
get |
yes | function ( WC_Product $product ) returning the value to edit |
set |
yes | function ( WC_Product $product, $value ) applying a new value |
group |
no | Groups related columns (default "Other") |
options |
for select and terms |
value => label pairs |
applies |
no | function ( WC_Product $product ) returning false where the field doesn't exist (the cell is greyed out) |
show |
no | function ( WC_Product $product ) returning true where the field can't be edited (applies is false) but its value should still be shown, greyed out, e.g. a value worked out from other fields |
hidden |
no | true to hide the column until switched on in Screen Options |
sort |
no | Makes it sortable: an orderby value for wc_get_products() (e.g. 'title'), or array( 'meta' => '_my_key', 'num' => true ) |
Types
| Type | Value | Edited with |
|---|---|---|
text |
string | a text box |
longtext |
HTML string | a larger text box over the cell |
price |
decimal string, '' for none |
a text box; shown in your currency |
number |
number as a string | a text box |
date |
Y-m-d string, '' for none |
a date picker |
select |
one of the options keys |
a dropdown |
bool |
'yes' or 'no' |
a Yes/No dropdown |
terms |
array of term IDs | a checkbox list of the options |
image |
attachment ID as a string, '' for none |
the media library |
images |
array of attachment IDs | the media library, several in order |
readonly |
string | shown, not editable |
Values arrive in set as the grid sends them: strings, or arrays of IDs for terms and images. Always write them through the product's own setters or meta functions, so WooCommerce and other plugins see the change.
Refusing a value
Throw an exception with a message for the shop manager. It appears under the cell in red, and that product isn't saved:
'set' => function ( WC_Product $product, $value ) {
$value = trim( (string) $value );
if ( '' !== $value && ! preg_match( '/^\d{8,14}$/', $value ) ) {
throw \Extendiment\Gridline\Columns::invalid( 'A GTIN is 8 to 14 digits.' );
}
$product->update_meta_data( '_gtin', $value );
},
Columns::invalid() returns an InvalidArgumentException; any InvalidArgumentException works.
Helpers
Extendiment\Gridline\Columns has the helpers the built-in columns use:
Columns::decimal( $value ): a number of 0 or more (or''), as WooCommerce stores it; refuses anything else.Columns::option( $value, $options ): one of the options' keys; refuses anything else.Columns::bool( $value ):truefor "yes", "1", "true" or "on".Columns::term_options( $taxonomy ): a taxonomy's terms asID => 'Parent › Child', ready foroptions.Columns::term_ids( $value, $options ): the term IDs, each one of the options.
// A brand taxonomy as a terms column.
add_filter( 'gridline_columns', function ( $columns ) {
$brands = \Extendiment\Gridline\Columns::term_options( 'product_brand' );
$columns['brands'] = array(
'label' => 'Brands',
'type' => 'terms',
'options' => $brands,
'applies' => fn( $p ) => ! $p->is_type( 'variation' ),
'get' => fn( $p ) => wp_get_post_terms( $p->get_id(), 'product_brand', array( 'fields' => 'ids' ) ),
'set' => fn( $p, $v ) => wp_set_post_terms( $p->get_id(), \Extendiment\Gridline\Columns::term_ids( $v, $brands ), 'product_brand' ),
);
return $columns;
} );
Where the column goes
Columns appear in the array's order. Adding a key puts the column at the end; to place it elsewhere, rebuild the array:
add_filter( 'gridline_columns', function ( $columns ) {
$at = array_search( 'sku', array_keys( $columns ), true ) + 1;
$new = array( 'gtin' => array( /* … */ ) );
return array_slice( $columns, 0, $at, true ) + $new + array_slice( $columns, $at, null, true );
} );
Gridline Pro adds its columns at priority 5, so columns added at the default priority 10 come after them.
Variable products and variations
Use applies to grey out cells where a field doesn't exist, for example fn( $p ) => ! $p->is_type( 'variable' ) for a field only simple products and variations have. With Gridline Pro, variations get rows of their own, so decide whether your field applies to them too.