I think that it is for regular users that work with views very difficult to get the machine name of a view and also to get the correct display id.
I wrote a patch to change the textfields for the "name" and the "display id" to dropdowns.
I also changed some tabs to spaces.
Please review it.
Any questions or remarks are very welcome.

Comments

g089h515r806’s picture

Status: Needs review » Needs work

Could you reroll your path to dev version?
I could not apply it.

g089h515r806’s picture

Make sure the old version still works correctly.

Change

$elements[$view_name.'_display_id']

back to

$elements['display_id']
daffie’s picture

Status: Needs work » Needs review
StatusFileSize
new3.22 KB

Oops, I did check out the master version from git and not the 7.x-1.x version.
The tabs are already changed to spaces in the dev version.
If have added an extra if-statement to make sure the old version will still work correctly.

An other option for this problem to combine name and display_id into one large dropdown element.
In views you have a header and a footer area. There you add the field "Global: View area".
The "View to insert" is a combined dropdown element.

g089h515r806’s picture

I think it will be better if use ajax to fetch the display options. THere is an example: http://drupal.org/sandbox/katbailey/1361118.

you could find the ajax code at here:

    $selected_view = (isset($settings['view_name']) ? $settings['view_name'] : (isset($views_keys[0]) ? $views_keys[0] : ''));
    $element['view_name'] = array(
      '#type' => 'select',
      '#options' => $views,
      '#default_value' => $selected_view,
      '#title' => t('Select a view'),
      '#ajax' => array(
        'event' => 'change',
        'callback' => '_er_formatter_views_dropdown_callback',
        'wrapper' => 'views-replace',
      ),
    );
    $element['view_display'] = array(
      '#prefix' => '<div id="views-replace">',
      '#suffix' => '</div>',
      '#type' => 'select',
      '#title' => 'display',
      '#options' => _er_formatter_get_views_displays($selected_view),
      '#default_value' => isset($settings['view_display']) ? $settings['view_display'] : '',
    );

....

/**
 * Ajax callback, triggered when view is changed.
 */
function _er_formatter_views_dropdown_callback($form, $form_state) {
  $location = $form_state['triggering_element']['#array_parents'];
  array_pop($location);
  $location[] = 'view_display';

  $item = drupal_array_get_nested_value($form, $location);
  return $item;
}

/**
 * Helper function to get all views.
 */
function _er_formatter_get_views() {
  $enabled_views = array();
  $views = views_get_enabled_views();

  foreach ($views as $view) {
    $enabled_views[$view->name] = $view->name;
  }
  ksort($enabled_views);
  return $enabled_views;
}

/**
 * Helper function to get all view displays.
 */
function _er_formatter_get_views_displays($view_name) {

  if (empty($view_name)) {
    // No view.
    return array();
  }

  $views = views_get_enabled_views();
  if (!isset($views[$view_name])) {
    return array();
  }

  $view = $views[$view_name];

  if (empty($view->display)) {
    // This view is broken.
    return array();
  }

  foreach ($view->display as $id => $display) {
    $displays[$id] = $id .': '. $display->display_title;
  }
  return $displays;
}
g089h515r806’s picture

Status: Needs review » Needs work

we could implement it in this way:

  $elements['name'] = array(
    '#type' => 'select',
    '#title' => t('Name'),
    '#options' => $views,
    '#default_value' => $settings['name'],
    '#description' => t('The machine name of the view to embed.'),
    '#ajax' => array(
      'event' => 'change',
      'callback' => '_field_collection_views_views_dropdown_callback',
      'wrapper' => 'views-display-id-replace',
    ),
  );
  $elements['display_id'] = array(
    '#prefix' => '<div id="views-display-id-replace">',
    '#suffix' => '</div>',
    '#type' => 'select',
    '#title' => t('Display id'),
    '#default_value' => $settings['display_id'],
    '#description' => t('The display id to embed.'),
    '#options' => _field_collection_views_get_views_displays($selected_view),
  );
g089h515r806’s picture

we could implement it in this way:

  $elements['name'] = array(
    '#type' => 'select',
    '#title' => t('Name'),
    '#options' => $views,
    '#default_value' => $settings['name'],
    '#description' => t('The machine name of the view to embed.'),
    '#ajax' => array(
      'event' => 'change',
      'callback' => '_field_collection_views_views_dropdown_callback',
      'wrapper' => 'views-display-id-replace',
    ),
  );
  $elements['display_id'] = array(
    '#prefix' => '<div id="views-display-id-replace">',
    '#suffix' => '</div>',
    '#type' => 'select',
    '#title' => t('Display id'),
    '#default_value' => $settings['display_id'],
    '#description' => t('The display id to embed.'),
    '#options' => _field_collection_views_get_views_displays($selected_view),
  );
daffie’s picture

I do not know why but with the ajax call there is no $form_build_id variable set. This in turn will result in a watchdog error: "Invalid form POST data.". The comments that are with the code (includes/ajax.inc) that generates this error is:
// If $form cannot be loaded from the cache, the form_build_id in $_POST
// must be invalid, which means that someone performed a POST request onto
// system/ajax without actually viewing the concerned form in the browser.
// This is likely a hacking attempt as it never happens under normal
// circumstances, so we just do nothing.

I have tried to use an ajax solution before and had the same problem. That is why I used an other solution to fix the problem. If you do not like this solution, what do you think of my suggestion in comment #3.

g089h515r806’s picture

Have you read the code of http://drupal.org/sandbox/katbailey/1361118, it use ajax and work correctly.

There is an issue about this module, http://drupal.org/node/1815116, and I have read the code of it, and found that it use dropdowns.

I think that it is not difficult to port the ajax code to this module, if you have problems, you could update your Drupal version to latest version. Maybe it is ok with latest version.

g089h515r806’s picture

There is an ajax issue associated with Entity Reference View Field Formatter, http://drupal.org/node/1623460 ,
It was fixed by merlinofchaos, the author of Views.

daffie’s picture

Yes I have read the code. I am not 100% sure but I think that katbaileys hook_field_formatter_settings_form() is being called an other location.
The ajax call alone will result in an error. The callback function does not even get called. If you add:

<?php
    '#ajax' => array(
      'event' => 'change',
      'callback' => '_field_collection_views_views_dropdown_callback',
      'wrapper' => 'views-display-id-replace',
    ),
?>

to the element "name". Add then select an other view, the ajax call is made and the watchdog log is the result. Maybe this is a views bug???

daffie’s picture

#9: As far as I can see. Their problem is in the ajax callback function. Our/my problem is that the callback function is not even reached. The variable $form_build_id is empty and this results in a watchdog error.

g089h515r806’s picture

I have fixed it using ajax.

daffie’s picture

I love to know how you did it.

g089h515r806’s picture

Here is the code:

/**
 * Implements hook_field_formatter_settings_form().
 */
function field_collection_views_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $display = $instance['display'][$view_mode];
  $settings = isset($form_state['values']['fields'][$field['field_name']]['settings_edit_form']) ? $form_state['values']['fields'][$field['field_name']]['settings_edit_form']['settings'] : $display['settings'];
  
  $views = array('' => t('-- Please select --')) + _field_collection_views_get_views();
  $views_keys = array_keys($views);

  $selected_view = (isset($settings['name']) ? $settings['name'] : (isset($views_keys[0]) ? $views_keys[0] : ''));

  $elements['name'] = array(
    '#type' => 'select',
    '#title' => t('Select a view'),
    '#options' => $views,
    '#default_value' => $selected_view,
    //'#description' => t('The machine name of the view to embed.'),
    '#ajax' => array(
      'event' => 'change',
      'callback' => '_field_collection_views_views_dropdown_callback',
      'wrapper' => 'views-replace',
    ),
  );
  $elements['display_id'] = array(
    '#prefix' => '<div id="views-replace">',
    '#suffix' => '</div>',
    '#type' => 'select',
    '#title' => t('Display'),
    '#options' => _field_collection_views_get_views_displays($selected_view),
    '#default_value' => isset($settings['display_id']) ? $settings['display_id'] : '',
    //'#description' => t('The display id to embed.'),
  );
  $elements['add'] = array(
    '#type' => 'textfield',
    '#title' => t('Add link title'),
    '#default_value' => $settings['add'],
    '#description' => t('Leave the title empty, to hide the link.'),
  );

  return $elements;
}

/**
 * Implements hook_field_formatter_settings_summary().
 */
function field_collection_views_field_formatter_settings_summary($field, $instance, $view_mode) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];

  $links = array_filter(array_intersect_key($settings, array_flip(array('name', 'display_id'))));
  if ($links) {
    return '<em>Embed View:</em> ' . check_plain(implode(', ', $links));
  }
  else {
    return t('Not showing any view.');
  }

}

/**
 * Implements hook_views_api().
 */
function field_collection_views_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'field_collection_views') . '/views',
  );
}

/**
 * Ajax callback, triggered when view is changed.
 */
function _field_collection_views_views_dropdown_callback($form, $form_state) {
  $location = $form_state['triggering_element']['#array_parents'];
  array_pop($location);
  $location[] = 'display_id';

  $item = drupal_array_get_nested_value($form, $location);
  return $item;
}

/**
 * Helper function to get all views.
 */
function _field_collection_views_get_views() {
  $enabled_views = array();
  $views = views_get_enabled_views();

  foreach ($views as $view) {
    if ($view->base_table == 'field_collection_item') {
      $enabled_views[$view->name] = $view->name;
    }
  }
  ksort($enabled_views);
  return $enabled_views;
}

/**
 * Helper function to get all view displays.
 */
function _field_collection_views_get_views_displays($view_name) {

  if (empty($view_name)) {
    // No view.
    return array();
  }

  $views = views_get_enabled_views();
  if (!isset($views[$view_name])) {
    return array();
  }

  $view = $views[$view_name];

  if (empty($view->display)) {
    // This view is broken.
    return array();
  }

  foreach ($view->display as $id => $display) {
    $displays[$id] = $id .': '. $display->display_title;
  }
  return $displays;
}
daffie’s picture

If it is working on your site, then there must be something wrong with my development site. Because I am getting the watchdog error "Invalid form POST data".

g089h515r806’s picture

Status: Needs work » Fixed

commited, grant the credit to your account, you have worked on this feature and fixed it first.

daffie’s picture

Thank you for the credit

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.