All of a sudden I am noticing that the Table formatted views on the site I'm developing have breakage site-wide, where the TD is not generated for fields that are empty, requiring a rewrite results to throw <div></div> in there if there is not value for that field.

The top row there has 9 <TD> cells, the lower has 7.

Anyone seen this before and know the cause?

Accepted answer

Found it thanks to your hints...I had shot my own foot trying to clean up PHP errors about nulls when exhausted.

So for anyone else, here is my view_view_table that works:

function vhb_bootstrap_preprocess_views_view_table(&$variables) {

$view = $variables['view'];

 

// We need the raw data for this grouping, which is passed in as $variables['rows'].

// However, the template also needs to use for the rendered fields. We

// therefore swap the raw data out to a new variable and reset $variables['rows']

// so that it can get rebuilt.

// Store rows so that they may be used by further preprocess functions.

$result = $variables['result'] = $variables['rows'];

$variables['rows'] = array();

$variables['field_classes'] = array();

$variables['header'] = array();

 

$options = $view->style_plugin->options;

$handler = $view->style_plugin;

 

$default_row_class = isset($options['default_row_class']) ? $options['default_row_class'] : TRUE;

$row_class_special = isset($options['row_class_special']) ? $options['row_class_special'] : TRUE;

 

$fields = &$view->field;

$columns = $handler->sanitize_columns($options['columns'], $fields);

 

$active = !empty($handler->active) ? $handler->active : '';

$order = !empty($handler->order) ? $handler->order : 'asc';

$responsive_columns = array();

 

$query = tablesort_get_query_parameters();

if (isset($view->exposed_raw_input)) {

$query += $view->exposed_raw_input;

}

 

// Fields must be rendered in order as of Views 2.3, so we will pre-render

// everything.

$renders = $handler->render_fields($result);

 

foreach ($columns as $field => $column) {

// Create a second variable so we can find what fields we have and what the

// CSS classes should be.

$variables['fields'][$field] = backdrop_clean_css_identifier($field);

if ($active == $field) {

$variables['fields'][$field] .= ' active';

}

 

// render the header labels

if ($field == $column && empty($fields[$field]->options['exclude'])) {

$label = check_plain(!empty($fields[$field]) ? $fields[$field]->label() : '');

if (empty($options['info'][$field]['sortable']) || !$fields[$field]->click_sortable()) {

$variables['header'][$field] = $label;

}

else {

$initial = !empty($options['info'][$field]['default_sort_order']) ? $options['info'][$field]['default_sort_order'] : 'asc';

 

if ($active == $field) {

$initial = ($order == 'asc') ? 'desc' : 'asc';

}

 

$title = t('sort by @s', array('@s' => $label));

if ($active == $field) {

$label .= theme('tablesort_indicator', array('style' => $initial));

}

 

$query['order'] = $field;

$query['sort'] = $initial;

$link_options = array(

'html' => TRUE,

'attributes' => array('title' => $title),

'query' => $query,

);

$variables['header'][$field] = l($label, $_GET['q'], $link_options);

}

 

$variables['header_classes'][$field] = array();

// Set up the header label class.

if ($fields[$field]->options['element_default_classes']) {

$variables['header_classes'][$field][] = "views-field";

$variables['header_classes'][$field][] = "views-field-" . $variables['fields'][$field];

}

$class = $fields[$field]->element_label_classes(0);

if ($class) {

$variables['header_classes'][$field][] = $class;

}

// Add a CSS align class to each field if one was set

if (!empty($options['info'][$field]['align'])) {

$variables['header_classes'][$field][] = backdrop_clean_css_identifier($options['info'][$field]['align']);

}

// Add active class.

if ($active == $field) {

$variables['header_classes'][$field][] = 'active';

}

 

// Add a header label wrapper if one was selected.

if ($variables['header'][$field]) {

$element_label_type = $fields[$field]->element_label_type(TRUE, TRUE);

if ($element_label_type) {

$variables['header'][$field] = '<' . $element_label_type . '>' . $variables['header'][$field] . '</' . $element_label_type . '>';

}

}

 

// Track responsive classes for each column as needed. Only the header

// cells for a column are marked up with the responsive classes by a

// module developer or themer. The responsive classes on the header cells

// must be transferred to the content cells.

if (in_array(RESPONSIVE_PRIORITY_MEDIUM, $variables['header_classes'][$field])) {

$responsive_columns[$field] = RESPONSIVE_PRIORITY_MEDIUM;

}

elseif (in_array(RESPONSIVE_PRIORITY_LOW, $variables['header_classes'][$field])) {

$responsive_columns[$field] = RESPONSIVE_PRIORITY_LOW;

}

}

 

// Add a CSS align class to each field if one was set

if (!empty($options['info'][$field]['align'])) {

$variables['fields'][$field] .= ' ' . backdrop_clean_css_identifier($options['info'][$field]['align']);

}

 

// Render each field into its appropriate column.

foreach ($result as $num => $row) {

// Add field classes and attributes.

$variables['field_attributes'][$field][$num] = array();

$variables['field_classes'][$field][$num] = array();

if ($fields[$field]->options['element_default_classes']) {

$variables['field_classes'][$field][$num][] = "views-field";

$variables['field_classes'][$field][$num][] = "views-field-" . $variables['fields'][$field];

}

// Copy RESPONSIVE_PRIORITY_LOW/RESPONSIVE_PRIORITY_MEDIUM

// class from header to cell as needed.

if (isset($responsive_columns[$field])) {

$variables['field_classes'][$field][$num][] = $responsive_columns[$field];

}

if ($classes = $fields[$field]->element_classes($num)) {

$classes_array = explode(' ', $classes);

$variables['field_classes'][$field][$num] = array_merge($variables['field_classes'][$field][$num], $classes_array);

}

 

if (!empty($fields[$field]) && empty($fields[$field]->options['exclude'])) {

$field_output = $renders[$num][$field];

// at this stage $field_output = the value of that field.

//modify classes for specific values

// should be harmless, as it all it does is add extra classes

$element_type = $fields[$field]->element_type(TRUE, TRUE); // eg DIV

if(!is_null($field_output)){ $cssval= str_replace(' ', '-', strtolower($field_output)); }

$cssfield=str_replace('_', '-', strtolower($field));

if ($element_type) {

$field_output = '<' . $element_type .' class="'.$cssfield.'-'.$cssval.'">' . $field_output . '</' . $element_type . '>';

}

 

// Don't bother with separators and stuff if the field does not show up.

if (empty($field_output) && !empty($variables['rows'][$num][$column])) {

continue;

}

 

// Place the field into the column, along with an optional separator.

if (!empty($variables['rows'][$num][$column])) {

if (!empty($options['info'][$column]['separator'])) {

$variables['rows'][$num][$column] .= filter_xss_admin($options['info'][$column]['separator']);

}

}

else {

$variables['rows'][$num][$column] = '';

}

 

$variables['rows'][$num][$column] .= $field_output;

}

}

 

// Remove columns if the option is hide empty column is checked and the field is not empty.

if (!empty($options['info'][$field]['empty_column'])) {

$empty = TRUE;

foreach ($variables['rows'] as $num => $columns) {

$empty &= empty($columns[$column]);

}

if ($empty) {

foreach ($variables['rows'] as $num => &$column_items) {

unset($column_items[$column]);

unset($variables['header'][$column]);

}

}

}

}

 

// Hide table header if all labels are empty.

if (!array_filter($variables['header'])) {

$variables['header'] = array();

}

 

$count = 0;

foreach ($variables['rows'] as $num => $row) {

$variables['row_classes'][$num] = array();

if ($row_class_special) {

$variables['row_classes'][$num][] = ($count++ % 2 == 0) ? 'odd' : 'even';

}

if ($row_class = $handler->get_row_class($num)) {

$variables['row_classes'][$num][] = $row_class;

}

}

 

if ($row_class_special) {

$variables['row_classes'][0][] = 'first';

$variables['row_classes'][count($variables['row_classes']) - 1][] = 'last';

}

 

$variables['classes'] = array('views-table');

if (empty($variables['rows']) && !empty($options['empty_table'])) {

$variables['rows'][0][0] = $view->display_handler->render_area('empty');

// Calculate the amounts of rows with output.

$variables['field_attributes'][0][0]['colspan'] = count($variables['header']);

$variables['field_classes'][0][0] = array('views-empty');

}

 

if (!empty($options['sticky'])) {

backdrop_add_js('core/misc/tableheader.js');

$variables['classes'][] = 'sticky-enabled';

}

 

// If the responsive classes were used, add the matching library.

if (count($responsive_columns)) {

backdrop_add_library('system', 'backdrop.tableresponsive');

// Add 'responsive-enabled' class to the table to identify it for JS.

// This is needed to target tables constructed by this function.

$variables['classes'][] = 'responsive-enabled';

}

$variables['classes'][] = 'cols-' . count($variables['header']);

 

// Add the summary to the list if set.

if (!empty($handler->options['summary'])) {

$variables['attributes'] = array('summary' => filter_xss_admin($handler->options['summary']));

}

 

// Add the caption to the list if set.

if (!empty($handler->options['caption'])) {

$variables['caption'] = filter_xss_admin($handler->options['caption']);

}

else {

$variables['caption'] = '';

}

}

 

Most helpful answers

Hmmm not sure, but check the following spots:

- In Format > Settings check the "Hide empty Column" checkboxes

 

- And then, in each individual field, check both options for "empty". By default the "hide rewriting" is selected, but "hide if empty" is not.

 

Comments

Hmmm not sure, but check the following spots:

- In Format > Settings check the "Hide empty Column" checkboxes

 

- And then, in each individual field, check both options for "empty". By default the "hide rewriting" is selected, but "hide if empty" is not.

 

Thanks, yeh, those settings are fine, and haven't changed. I'm going to need to wander through the settings recently made in other modules. I just wondered if this had been seen before. I started with D6, back in the day,  and haven't! 

Never seen that before. Are you using a custom template for the view?

Not specifically for that view, and this problem is now on every table view. But yes at template.php level there are a lot of customisations.

Found it thanks to your hints...I had shot my own foot trying to clean up PHP errors about nulls when exhausted.

So for anyone else, here is my view_view_table that works:

function vhb_bootstrap_preprocess_views_view_table(&$variables) {

$view = $variables['view'];

 

// We need the raw data for this grouping, which is passed in as $variables['rows'].

// However, the template also needs to use for the rendered fields. We

// therefore swap the raw data out to a new variable and reset $variables['rows']

// so that it can get rebuilt.

// Store rows so that they may be used by further preprocess functions.

$result = $variables['result'] = $variables['rows'];

$variables['rows'] = array();

$variables['field_classes'] = array();

$variables['header'] = array();

 

$options = $view->style_plugin->options;

$handler = $view->style_plugin;

 

$default_row_class = isset($options['default_row_class']) ? $options['default_row_class'] : TRUE;

$row_class_special = isset($options['row_class_special']) ? $options['row_class_special'] : TRUE;

 

$fields = &$view->field;

$columns = $handler->sanitize_columns($options['columns'], $fields);

 

$active = !empty($handler->active) ? $handler->active : '';

$order = !empty($handler->order) ? $handler->order : 'asc';

$responsive_columns = array();

 

$query = tablesort_get_query_parameters();

if (isset($view->exposed_raw_input)) {

$query += $view->exposed_raw_input;

}

 

// Fields must be rendered in order as of Views 2.3, so we will pre-render

// everything.

$renders = $handler->render_fields($result);

 

foreach ($columns as $field => $column) {

// Create a second variable so we can find what fields we have and what the

// CSS classes should be.

$variables['fields'][$field] = backdrop_clean_css_identifier($field);

if ($active == $field) {

$variables['fields'][$field] .= ' active';

}

 

// render the header labels

if ($field == $column && empty($fields[$field]->options['exclude'])) {

$label = check_plain(!empty($fields[$field]) ? $fields[$field]->label() : '');

if (empty($options['info'][$field]['sortable']) || !$fields[$field]->click_sortable()) {

$variables['header'][$field] = $label;

}

else {

$initial = !empty($options['info'][$field]['default_sort_order']) ? $options['info'][$field]['default_sort_order'] : 'asc';

 

if ($active == $field) {

$initial = ($order == 'asc') ? 'desc' : 'asc';

}

 

$title = t('sort by @s', array('@s' => $label));

if ($active == $field) {

$label .= theme('tablesort_indicator', array('style' => $initial));

}

 

$query['order'] = $field;

$query['sort'] = $initial;

$link_options = array(

'html' => TRUE,

'attributes' => array('title' => $title),

'query' => $query,

);

$variables['header'][$field] = l($label, $_GET['q'], $link_options);

}

 

$variables['header_classes'][$field] = array();

// Set up the header label class.

if ($fields[$field]->options['element_default_classes']) {

$variables['header_classes'][$field][] = "views-field";

$variables['header_classes'][$field][] = "views-field-" . $variables['fields'][$field];

}

$class = $fields[$field]->element_label_classes(0);

if ($class) {

$variables['header_classes'][$field][] = $class;

}

// Add a CSS align class to each field if one was set

if (!empty($options['info'][$field]['align'])) {

$variables['header_classes'][$field][] = backdrop_clean_css_identifier($options['info'][$field]['align']);

}

// Add active class.

if ($active == $field) {

$variables['header_classes'][$field][] = 'active';

}

 

// Add a header label wrapper if one was selected.

if ($variables['header'][$field]) {

$element_label_type = $fields[$field]->element_label_type(TRUE, TRUE);

if ($element_label_type) {

$variables['header'][$field] = '<' . $element_label_type . '>' . $variables['header'][$field] . '</' . $element_label_type . '>';

}

}

 

// Track responsive classes for each column as needed. Only the header

// cells for a column are marked up with the responsive classes by a

// module developer or themer. The responsive classes on the header cells

// must be transferred to the content cells.

if (in_array(RESPONSIVE_PRIORITY_MEDIUM, $variables['header_classes'][$field])) {

$responsive_columns[$field] = RESPONSIVE_PRIORITY_MEDIUM;

}

elseif (in_array(RESPONSIVE_PRIORITY_LOW, $variables['header_classes'][$field])) {

$responsive_columns[$field] = RESPONSIVE_PRIORITY_LOW;

}

}

 

// Add a CSS align class to each field if one was set

if (!empty($options['info'][$field]['align'])) {

$variables['fields'][$field] .= ' ' . backdrop_clean_css_identifier($options['info'][$field]['align']);

}

 

// Render each field into its appropriate column.

foreach ($result as $num => $row) {

// Add field classes and attributes.

$variables['field_attributes'][$field][$num] = array();

$variables['field_classes'][$field][$num] = array();

if ($fields[$field]->options['element_default_classes']) {

$variables['field_classes'][$field][$num][] = "views-field";

$variables['field_classes'][$field][$num][] = "views-field-" . $variables['fields'][$field];

}

// Copy RESPONSIVE_PRIORITY_LOW/RESPONSIVE_PRIORITY_MEDIUM

// class from header to cell as needed.

if (isset($responsive_columns[$field])) {

$variables['field_classes'][$field][$num][] = $responsive_columns[$field];

}

if ($classes = $fields[$field]->element_classes($num)) {

$classes_array = explode(' ', $classes);

$variables['field_classes'][$field][$num] = array_merge($variables['field_classes'][$field][$num], $classes_array);

}

 

if (!empty($fields[$field]) && empty($fields[$field]->options['exclude'])) {

$field_output = $renders[$num][$field];

// at this stage $field_output = the value of that field.

//modify classes for specific values

// should be harmless, as it all it does is add extra classes

$element_type = $fields[$field]->element_type(TRUE, TRUE); // eg DIV

if(!is_null($field_output)){ $cssval= str_replace(' ', '-', strtolower($field_output)); }

$cssfield=str_replace('_', '-', strtolower($field));

if ($element_type) {

$field_output = '<' . $element_type .' class="'.$cssfield.'-'.$cssval.'">' . $field_output . '</' . $element_type . '>';

}

 

// Don't bother with separators and stuff if the field does not show up.

if (empty($field_output) && !empty($variables['rows'][$num][$column])) {

continue;

}

 

// Place the field into the column, along with an optional separator.

if (!empty($variables['rows'][$num][$column])) {

if (!empty($options['info'][$column]['separator'])) {

$variables['rows'][$num][$column] .= filter_xss_admin($options['info'][$column]['separator']);

}

}

else {

$variables['rows'][$num][$column] = '';

}

 

$variables['rows'][$num][$column] .= $field_output;

}

}

 

// Remove columns if the option is hide empty column is checked and the field is not empty.

if (!empty($options['info'][$field]['empty_column'])) {

$empty = TRUE;

foreach ($variables['rows'] as $num => $columns) {

$empty &= empty($columns[$column]);

}

if ($empty) {

foreach ($variables['rows'] as $num => &$column_items) {

unset($column_items[$column]);

unset($variables['header'][$column]);

}

}

}

}

 

// Hide table header if all labels are empty.

if (!array_filter($variables['header'])) {

$variables['header'] = array();

}

 

$count = 0;

foreach ($variables['rows'] as $num => $row) {

$variables['row_classes'][$num] = array();

if ($row_class_special) {

$variables['row_classes'][$num][] = ($count++ % 2 == 0) ? 'odd' : 'even';

}

if ($row_class = $handler->get_row_class($num)) {

$variables['row_classes'][$num][] = $row_class;

}

}

 

if ($row_class_special) {

$variables['row_classes'][0][] = 'first';

$variables['row_classes'][count($variables['row_classes']) - 1][] = 'last';

}

 

$variables['classes'] = array('views-table');

if (empty($variables['rows']) && !empty($options['empty_table'])) {

$variables['rows'][0][0] = $view->display_handler->render_area('empty');

// Calculate the amounts of rows with output.

$variables['field_attributes'][0][0]['colspan'] = count($variables['header']);

$variables['field_classes'][0][0] = array('views-empty');

}

 

if (!empty($options['sticky'])) {

backdrop_add_js('core/misc/tableheader.js');

$variables['classes'][] = 'sticky-enabled';

}

 

// If the responsive classes were used, add the matching library.

if (count($responsive_columns)) {

backdrop_add_library('system', 'backdrop.tableresponsive');

// Add 'responsive-enabled' class to the table to identify it for JS.

// This is needed to target tables constructed by this function.

$variables['classes'][] = 'responsive-enabled';

}

$variables['classes'][] = 'cols-' . count($variables['header']);

 

// Add the summary to the list if set.

if (!empty($handler->options['summary'])) {

$variables['attributes'] = array('summary' => filter_xss_admin($handler->options['summary']));

}

 

// Add the caption to the list if set.

if (!empty($handler->options['caption'])) {

$variables['caption'] = filter_xss_admin($handler->options['caption']);

}

else {

$variables['caption'] = '';

}

}