I am building a simple custom module to search a certain node type and displaying it in the same page as the form. It is like the search function. The problem is how to display the result below the form with paging-teaser node style?
The code is:
<?php
/**
* Implements hook_help().
*
* Displays help and module information.
*
* @param path
* Which path of the site we're using to display help
* @param arg
* Array that holds the current path as returned from arg() function
*/
function book_search_help($path, $arg) {
switch ($path) {
case "admin/help#book_search":
return '<p>' . t("Displays book search page") . '</p>';
break;
}
}
function book_search_menu() {
$items = array();
$items['book/search'] = array(
'title' => 'Pencarian book',
'description' => 'Halaman pencarian book',
'page callback' => 'drupal_get_form',
'page arguments' => array('book_search_form'),
'access arguments' => array('access content'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function book_search_form($form, &$form_state) {
$form['cari'] = array(
'#type' => 'fieldset',
//'#title' => t('Pencarian'),
//'#attributes' => array('class' => array('container-inline')),
'#tree' => TRUE,
);
$form['cari']['pilihan'] = array(
'#type' => 'select',
'#title' => t('Pilihan Pencarian'),
'#options' => array(
'1' => t('Option 1'),
'2' => t('Option 2'),
'3' => t('Option 3'),
'4' => t('Option 4'),
'5' => t('Option 5'),
'6' => t('Option 6'),
'7' => t('Option 7'),
'8' => t('Option 8'),
),
'#attributes' => array('class' => array('container-inline')),
'#default_value' => $category['umum'],
// '#description' => t('Set this to <em>Yes</em> if you would like this category to be selected by default.'),
);
$form['cari']['kata'] = array(
'#type' => 'textfield',
'#title' => t('Kata Kunci'),
'#size' => 50,
'#maxlength' => 256,
);
$form['cari']['submit'] = array('#type' => 'submit', '#value' => t('Cari'),'#submit' => array('book_search_submit'),);
if (isset ($form_state['hasil'])){
print render(node_view_multiple($form_state['hasil'], 'teaser')) . theme('pager');
}
return $form;
}
function book_search_submit($form, &$form_state) {
//db_query("INSERT INTO {table} (name, log, hidden) VALUES ('%s', %d, '%s')", $form_state['values']['name'], $form_state['values']['access']['log'], $form_state['values']['hidden']);
$query = new EntityFieldQuery;
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'mytype')
->pager(20)
->propertyCondition('status', 1); // in case you need it
// ->fieldCondition('field_customfield3', 'value', $user->uid)
// ->fieldCondition('field_customfield4', 'value', $anemailaddress);
$results = $query->execute();
if (isset($results['node'])) {
$news_items_nids = array_keys($results['node']);
$news_items = entity_load('node', $news_items_nids);
}
drupal_set_message(t('Your form has been submitted.'));
$nodes = node_load_multiple(array_keys($results['node']));
$form_state['hasil'] = $nodes;
// print render(node_view_multiple($nodes, 'teaser')) . theme('pager');
$form_state['rebuild'] = TRUE;
}
I modified the code so it can dynamically building queries according to selection options. The trick to display the result is by appending the result html in the back of the form code using $form['#suffix'] = $html;
. It resulting inconsistency in the result paging. Is there any way to improve it or make it right?
Modified Code:
function book_search_help($path, $arg) {
switch ($path) {
case "admin/help#book_search":
return '<p>' . t("Displays book search page") . '</p>';
break;
}
}
function book_search_menu() {
$items = array();
$items['book/search'] = array(
'title' => 'Pencarian book',
'description' => 'Halaman pencarian book',
'page callback' => 'drupal_get_form',
'page arguments' => array('book_search_form'),
'access arguments' => array('access content'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function book_search_form($form, &$form_state) {
$form['cari'] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
);
$form['cari']['pilihan'] = array(
'#type' => 'select',
'#title' => t('Pilihan Pencarian'),
'#options' => array(
'1' => t('1'),
'2' => t('2'),
'3' => t('3'),
'4' => t('4'),
'5' => t('5'),
'6' => t('6'),
'7' => t('7'),
'8' => t('8'),
),
'#attributes' => array('class' => array('container-inline')),
'#default_value' => $category['umum'],
);
$form['cari']['kata'] = array(
'#type' => 'textfield',
'#title' => t('Kata Kunci'),
'#size' => 50,
'#maxlength' => 256,
);
$form['cari']['submit'] = array('#type' => 'submit', '#value' => t('Cari'),'#submit' => array('book_search_submit'),);
if (isset($_SESSION['hasil'])){
$html = drupal_render(node_view_multiple($_SESSION['hasil'], 'teaser')) . theme('pager');
$form['#suffix'] = $html;
}
return $form;
}
function book_search_submit($form, &$form_state) {
$query = new EntityFieldQuery;
$query->entityCondition('entity_type', 'node');
switch($form_state['values']['cari']['pilihan']){
case '1':
$query->entityCondition('bundle', array('montype','book'), 'IN')
->fieldCondition('body', 'value', $form_state['values']['cari']['kata'], 'CONTAINS');
break;
case '2':
$query->entityCondition('bundle', 'montype')
->fieldCondition('body', 'value', $form_state['values']['cari']['kata'], 'CONTAINS');
break;
case '3':
$query->entityCondition('bundle', 'montype')
->fieldCondition('field_dosis', 'value', $form_state['values']['cari']['kata'], 'CONTAINS');
break;
case '4':
$query->entityCondition('bundle', 'montype')
->fieldCondition('field_efek_samping', 'value', $form_state['values']['cari']['kata'], 'CONTAINS');
break;
case '5':
$query->entityCondition('bundle', 'montype')
->fieldCondition('field_peringatan', 'value', $form_state['values']['cari']['kata'], 'CONTAINS');
break;
case '6':
$query->entityCondition('bundle', 'montype')
->fieldCondition('field_interaksi', 'value', $form_state['values']['cari']['kata'], 'CONTAINS');
break;
case '7':
$query->entityCondition('bundle', 'montype')
->fieldCondition('field_kontraindikasi', 'value', $form_state['values']['cari']['kata'], 'CONTAINS');
break;
case '8':
$query->entityCondition('bundle', 'montype')
->propertyCondition('title', $form_state['values']['cari']['kata'], 'CONTAINS');
break;
default:
break;
}
$query->pager(20)
->propertyCondition('status', 1); // in case you need it
$results = $query->execute();
$_SESSION['hasil'] = node_load_multiple(array_keys($results['node']));
$form_state['rebuild'] = TRUE;
drupal_set_message(t('Your form has been submitted.'));
}
Just had a quick rewrite of a couple of aspects, didn't test it so there might be the odd typo or two. The only thing I've really added other than a couple of standards is the use of $form_state['storage'], which is primary used for multi-step forms, but I've used it a couple of times to achieve what you are trying to do. (https://www.drupal.org/node/1850410)
Also, the use of render instead of drupal_render, just does some additional checking before sending it over to the drupal_render function.
/**
* Implements hook_menu().
*/
function book_search_menu() {
$items = array();
$items['book/search'] = array(
'title' => 'Pencarian book',
'description' => 'Halaman pencarian book',
'page callback' => 'drupal_get_form',
'page arguments' => array('book_search_form'),
'access arguments' => array('access content'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/**
* Implements hook_form().
*/
function book_search_form($form, &$form_state) {
$results = _book_search_results();
$query = $results['query'];
$nids = $results['nids'];
$form['#method'] = 'get';
$form['#token'] = FALSE;
$form['#multistep'] = TRUE;
$form['#redirect'] = FALSE;
$form['#after_build'] = array('_book_search_form_after_build');
$form['cari'] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
);
$form['cari']['pilihan'] = array(
'#type' => 'select',
'#title' => t('Pilihan Pencarian'),
'#options' => array(
'1' => t('1'),
'2' => t('2'),
'3' => t('3'),
'4' => t('4'),
'5' => t('5'),
'6' => t('6'),
'7' => t('7'),
'8' => t('8'),
),
'#attributes' => array('class' => array('container-inline')),
'#default_value' => $query['pilihan'],
);
$form['cari']['kata'] = array(
'#type' => 'textfield',
'#title' => t('Kata Kunci'),
'#size' => 50,
'#maxlength' => 256,
'#default_value' => $query['kata'],
);
$form['cari']['submit'] = array(
'#type' => 'submit',
'#value' => t('Cari'),
'#submit' => array('book_search_form_submit'),
);
if ($nids) {
$nodes = node_load_multiple($nids);
// $build = _book_search_results_node($nodes);
$build = _book_search_results_table($nodes);
if ($build) {
$form['results'] = array(
'#type' => 'markup',
'#markup' => render($build) . theme('pager'),
);
}
}
return $form;
}
/**
* Remove items from the form in a after_build event.
*
* @param array $form
* The drupal form.
*
* @return array
* The drupal form, post modifications.
*/
function _book_search_form_after_build($form) {
unset($form['form_token']);
unset($form['form_build_id']);
unset($form['form_id']);
return $form;
}
/**
* Get results by using filters in the query string.
*
* @return array
* An array of node id's.
*/
function _book_search_results() {
$values = drupal_get_query_parameters();
$field_values = array(
'pilihan' => FALSE,
'kata' => '',
);
// @todo: You may need to update these variables.
$cari = array_key_exists('cari', $values) && is_array($values['cari']) ? $values['cari'] : array();
// If the user has not submitted the form.
if (!$cari) {
$field_values = array(
'pilihan' => '7',
'kata' => 'searchterm',
);
}
$query = array(
'pilihan' => array_key_exists('pilihan', $cari) ? $cari['pilihan'] : $field_values['pilihan'],
'kata' => array_key_exists('kata', $cari) ? $cari['kata'] : $field_values['kata'],
);
$bundles = array('montype');
$field_conditions = array(
'1' => 'body',
'2' => 'body',
'3' => 'field_dosis',
'4' => 'field_efek_samping',
'5' => 'field_peringatan',
'6' => 'field_interaksi',
'7' => 'field_kontraindikasi',
);
$propery_conditions = array('title');
if ($query['pilihan'] == '1') {
$bundles[] = 'book';
}
$efquery = new EntityFieldQuery();
$efquery->entityCondition('entity_type', 'node')
->entityCondition('bundle', $bundles);;
if ($query['pilihan']) {
if (array_key_exists($query['kata'], $field_conditions)) {
$efquery->fieldCondition($field_conditions[$query['pilihan']], 'value', $query['kata'], 'CONTAINS');
}
elseif (array_key_exists($query['pilihan'], $propery_conditions)) {
$efquery->propertyCondition($propery_conditions[$query['pilihan']], $query['kata'], 'CONTAINS');
}
}
$results = $efquery->pager(20)
->execute();
return array(
'query' => $query,
'nids' => $results ? array_keys($results['node']) : array(),
);
}
/**
* Node teaser display for the results of the book search.
*
* @param array $nodes
* An array of nodes.
*
* @return array
* A renderable build array.
*/
function _book_search_results_node(array $nodes) {
return node_view_multiple($nodes, 'teaser');
}
/**
* Table display for the results of the book search.
*
* @param array $nodes
* An array of nodes.
*
* @return array
* A renderable build array.
*/
function _book_search_results_table(array $nodes) {
$build = array(
'#theme' => 'table',
'#header' => array(
t('Node Id'),
t('Title'),
t('Created'),
t('Random field'),
),
'#attributes' => array(
'class' => array('book-search-results-table'),
),
'#rows' => array(),
'#sticky' => FALSE,
'#empty' => t('There are no results matching that criteria.'),
);
foreach ($nodes as $n) {
$field_random_field = field_get_items('node', $n, 'field_random_field');
$random_field = $field_random_field ? $field_random_field[0]['value'] : '';
$build['#rows'][] = array(
$n->nid,
$n->title,
$n->created,
$random_field,
);
}
return $build;
}