This function will delete a specific row of values from an existing repeater field or flexible content sub field value. This function is different to delete_row() which will delete a row from a parent field. You may use this function inside or outside of a have_rows() loop to target which sub field’s value you intend to modify.


  • Added in version 5.4.7


delete_sub_row( $selector, $i, $post_id );
  • $selector: (mixed) The sub field name or key, or an array of ancestors and row numbers (required)
  • $i: (int) The row number you wish to delete (required)
  • $post_id: (mixed) The post ID of which the value is saved to


This function will return true upon success or false upon failure.


  • Row numbers start from 1 (not 0). For example, the first row of values is considered $i = 1
  • It is possible to change the row index starting point so that row numbers start from 0 using the row_index_offset setting.


The following examples use a repeater field called ‘Parent’ that contains a child repeater. Here is an illustration of the sub fields:

r1 (repeater)
– r2 (repeater)
— t1 (text)
— t2 (text)

Inside have_rows() loop

This example will loop through a repeater field (r1) and delete the first row from each sub repeater field (r2).


if( have_rows('r1') ) {

	while( have_rows('r1') ) {

		delete_sub_row('r2', 1);




Outside have_rows() loop

This example will delete a row of values from a sub field outside of a have_rows() loop. Please note that the $selector parameter is given an array containing a mixture of field names and row numbers. This array should read from left to right, the parents to children relationship padded by the row number.


// delete r1 (row 1) => r2 (row 1)
delete_sub_row( array('r1', 1, 'r2'), 1 );

// delete r1 (row 1) => r2 (row 2)
delete_sub_row( array('r1', 1, 'r2'), 2 );

// delete r1 (row 2) => r2 (row 1)
delete_sub_row( array('r1', 2, 'r2'), 1 );