Problem Checkbox!

Events happening in the community are now at Drupal community events on www.drupal.org.
nicoksq's picture

Hola a todos, quería consultar porque estoy luchando con algo hace ya dos días, y no lo puedo descular.

Cree un modulo, que en el primer paso te pregunta un nombre, en un segundo paso te da para anotar unas fechas, y en el tercer paso se genera una tabla, con los artículos que hay entre esas fechas, lo que yo quería hacer, es que seleccionando esos checkbox(que están en la tabla), cuando pongo save, me retorne los checked. Actualmente, selecciono todos o uno solo, y me llega en el submit como si no hubiese seleccionado ninguno.

<?php
function get_nodes($dateIni,$dateEnd){
  $timestampInicio = strtotime($dateIni);
  $timestampFin = strtotime($dateEnd);

  $result = db_query(
      "SELECT nid,title,created FROM {node} WHERE type='Article' AND status=1 AND created BETWEEN $timestampInicio AND $timestampFin ORDER BY created DESC"
  );
  $nodes = $result->fetchAll();

  return $nodes;
}

function newsletter_abz_wizard($form, &$form_state, $no_js_use = FALSE) {

  // Provide a wrapper around the entire form, since we'll replace the whole
  // thing with each submit.
  $form['#prefix'] = '<div id="wizard-form-wrapper">';
  $form['#suffix'] = '</div>';
  // We want to deal with hierarchical form values.
  $form['#tree'] = TRUE;


  // $form_state['storage'] has no specific drupal meaning, but it is
  // traditional to keep variables for multistep forms there.
  $step = empty($form_state['storage']['step']) ? 1 : $form_state['storage']['step'];

  $form_state['storage']['step'] = $step;

  switch ($step) {
    case 1:
      $form['step1'] = array(
        '#type' => 'fieldset',
        '#title' => t('Step 1: Campaign Title'),
      );
      $form['step1']['name'] = array(
        '#type' => 'textfield',
        '#title' => t('Campaign Title'),
        '#default_value' => empty($form_state['values']['step1']['name']) ? '' : $form_state['values']['step1']['name'],
        '#required' => TRUE,
      );
      break;

    case 2:
      $form['step2'] = array(
        '#type' => 'fieldset',
        '#title' => t('Step 2: Find items between dates'),
      );
      $form['step2']['date_one'] = array(
          '#type' => 'textfield',
          '#title' => "De:",
          '#required' => TRUE,
          '#date_format' => 'd-F-Y',
          '#description' => "Ingrese la fecha.",
          '#default_value' => empty($form_state['values']['step2']['date_one']) ? '31-12-2015' : $form_state['values']['step2']['date_one'],
      );
      $form['step2']['date_two'] = array(
          '#type' => 'textfield',
          '#title' => "Hasta:",
          '#required' => TRUE,
          '#date_format' => 'd-F-Y',
          '#description' => "Ingrese la fecha.",
          '#default_value' => empty($form_state['values']['step2']['date_two']) ? date('d-m-Y',time()) : $form_state['values']['step2']['date_two'],
      );
      break;

    case 3:
      $form['step3'] = array(
        '#type' => 'fieldset',
        '#title' => t('Step 3: Select Articles'),
      );

      $nodes = get_nodes($form_state['values']['step2']['date_one'],$form_state['values']['step2']['date_two']);

      foreach($nodes as $node){

//ACA GENERO LOS CHECKBOX
        $form['step3']['select'][$node->nid] = array(
            '#type' => 'checkbox',
        );


        $form_checkbox = drupal_render($form['step3']['select'][$node->nid]);

        $rows[] = array(
            $form_checkbox,
            $node->nid,
            $node->title,
            date('d-m-Y',$node->created)
        );

      }

      $form['step3']['table'] = array(
          '#theme' => 'table',
          '#header' => array(
              t('Select'),
              t('Id'),
              t('Title'),
              t('Created')
          ),
          '#rows' => $rows,
      );

      break;
  }

  if ($step == 3) {
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t("Save Campaign"),
    );
  }
  if ($step < 3) {
    $form['next'] = array(
      '#type' => 'submit',
      '#value' => t('Next step'),
      '#ajax' => array(
        'wrapper' => 'wizard-form-wrapper',
        'callback' => 'newsletter_abz_wizard_callback',
      ),
    );
  }
  if ($step > 1) {
    $form['prev'] = array(
      '#type' => 'submit',
      '#value' => t("Previous step"),

      // Since all info will be discarded, don't validate on 'prev'.
      '#limit_validation_errors' => array(),
      // #submit is required to use #limit_validation_errors
      '#submit' => array('newsletter_abz_wizard_submit'),
      '#ajax' => array(
        'wrapper' => 'wizard-form-wrapper',
        'callback' => 'newsletter_abz_wizard_callback',
      ),
    );
  }


  if ($no_js_use) {
    unset($form['next']['#ajax']);
    unset($form['prev']['#ajax']);
  }

  return $form;
}

/
* Newsletter ABZ callback function.
*
* @param array $form
*   Form API form.
* @param array $form_state
*   Form API form.
*
* @return array
*   Form array.
*/
function newsletter_abz_wizard_callback($form, $form_state) {
  return $form;
}

/

*
* In AJAX this is only submitted when the final submit button is clicked,
* but in the non-javascript situation, it is submitted with every
* button click.
*/
function newsletter_abz_wizard_submit($form, &$form_state) {

  // Save away the current information.
  $current_step = 'step' . $form_state['storage']['step'];

  if (!empty($form_state['values'][$current_step])) {
    $form_state['storage']['values'][$current_step] = $form_state['values'][$current_step];
  }

  // Increment or decrement the step as needed. Recover values if they exist.
  if ($form_state['triggering_element']['#value'] == t('Next step')) {
    $form_state['storage']['step']++;
    // If values have already been entered for this step, recover them from
    // $form_state['storage'] to pre-populate them.
    $step_name = 'step' . $form_state['storage']['step'];
    if (!empty($form_state['storage']['values'][$step_name])) {
      $form_state['values'][$step_name] = $form_state['storage']['values'][$step_name];
    }
  }
  if ($form_state['triggering_element']['#value'] == t('Previous step')) {
    $form_state['storage']['step']--;
    // Recover our values from $form_state['storage'] to pre-populate them.
    $step_name = 'step' . $form_state['storage']['step'];
    $form_state['values'][$step_name] = $form_state['storage']['values'][$step_name];
  }
//die($form_state['triggering_element']['#value'] );
  // If they're done, submit.
  if ($form_state['triggering_element']['#value'] == t('Save Campaign')) {
    $value_message = t('Your information has been submitted:') . ' ';
die(var_dump($form_state));
    foreach ($form_state['storage']['values'] as $step => $values) {
      $value_message .= "$step: ";
      foreach ($values as $key => $value) {
        $value_message .= "$key=$value, ";
      }
    }
    drupal_set_message($value_message);
    $form_state['rebuild'] = FALSE;
    return;
  }

  // Otherwise, we still have work to do.
  $form_state['rebuild'] = TRUE;
}

Comments

Tu solución es tableselect

jncruces's picture

Si usas drupal_render, los elementos de formulario renderizados no se asocian al formulario donde los estás incrustando. Para eso tenemos tableselect:

function get_nodes($dateIni,$dateEnd){
  $timestampInicio = strtotime($dateIni);
  $timestampFin = strtotime($dateEnd);

  // $result = db_query(
  //     "SELECT nid,title,created FROM {node} WHERE type='Article' AND status=1 AND created BETWEEN $timestampInicio AND $timestampFin ORDER BY created DESC"
  // );

  $query = db_select('node', 'n')
  ->fields('n')
  ->condition('n.created', $timestampInicio, '>')
  ->condition('n.created', $timestampFin, '<=')
  // ->condition('n.type', 'page', '=')
  ->orderBy('n.created', 'DESC');
  $nodes=$query->execute()
  ->fetchAll();

  // $nodes = $result->fetchAll();

  return $nodes;
}

function newsletter_abz_wizard($form, &$form_state, $no_js_use = FALSE) {

  // Provide a wrapper around the entire form, since we'll replace the whole
  // thing with each submit.
  $form['#prefix'] = '<div id="wizard-form-wrapper">';
  $form['#suffix'] = '</div>';
  // We want to deal with hierarchical form values.
  $form['#tree'] = TRUE;


  // $form_state['storage'] has no specific drupal meaning, but it is
  // traditional to keep variables for multistep forms there.
  $step = empty($form_state['storage']['step']) ? 1 : $form_state['storage']['step'];

  $form_state['storage']['step'] = $step;

  switch ($step) {
    case 1:
      $form['step1'] = array(
        '#type' => 'fieldset',
        '#title' => t('Step 1: Campaign Title'),
      );
      $form['step1']['name'] = array(
        '#type' => 'textfield',
        '#title' => t('Campaign Title'),
        '#default_value' => empty($form_state['values']['step1']['name']) ? '' : $form_state['values']['step1']['name'],
        '#required' => TRUE,
      );
    break;
    case 2:
      $form['step2'] = array(
        '#type' => 'fieldset',
        '#title' => t('Step 2: Find items between dates'),
      );
      $form['step2']['date_one'] = array(
          '#type' => 'date_popup',
          '#title' => "De:",
          '#required' => TRUE,
          '#date_format' => 'd-m-Y',
          '#description' => "Ingrese la fecha.",
          '#default_value' => empty($form_state['values']['step2']['date_one']) ? '31-12-2015' : $form_state['values']['step2']['date_one'],
      );
      $form['step2']['date_two'] = array(
          '#type' => 'date_popup',
          '#title' => "Hasta:",
          '#required' => TRUE,
          '#date_format' => 'd-m-Y',
          '#description' => "Ingrese la fecha.",
          '#default_value' => empty($form_state['values']['step2']['date_two']) ? date('d-m-Y',time()) : $form_state['values']['step2']['date_two'],
      );
    break;
    case 3:
      $form['step3'] = array(
        '#type' => 'fieldset',
        '#title' => t('Step 3: Select Articles'),
      );

      $nodes = get_nodes($form_state['values']['step2']['date_one'],$form_state['values']['step2']['date_two']);
      foreach($nodes as $node) {
        // //ACA GENERO LOS CHECKBOX
        $rows[$node->nid] = array(
          'id' => $node->nid,
          'title' =>  $node->title,
          'created' => date('d-m-Y',$node->created)
        );
      }
      $form['step3']['table'] = array(
          '#type' => 'tableselect',
          '#header' => array(
              'id' => t('Id'),
              'title' => t('Title'),
              'created' => t('Created')
          ),
          '#options' => $rows,
      );
      break;
  }

  if ($step == 3) {
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t("Save Campaign"),
    );
  }
  if ($step < 3) {
    $form['next'] = array(
      '#type' => 'submit',
      '#value' => t('Next step'),
      '#ajax' => array(
        'wrapper' => 'wizard-form-wrapper',
        'callback' => 'newsletter_abz_wizard_callback',
      ),
    );
  }
  if ($step > 1) {
    $form['prev'] = array(
      '#type' => 'submit',
      '#value' => t("Previous step"),

      // Since all info will be discarded, don't validate on 'prev'.
      '#limit_validation_errors' => array(),
      // #submit is required to use #limit_validation_errors
      '#submit' => array('newsletter_abz_wizard_submit'),
      '#ajax' => array(
        'wrapper' => 'wizard-form-wrapper',
        'callback' => 'newsletter_abz_wizard_callback',
      ),
    );
  }


  if ($no_js_use) {
    unset($form['next']['#ajax']);
    unset($form['prev']['#ajax']);
  }

  return $form;
}

/
* Newsletter ABZ callback function.
*
* @param array $form
*   Form API form.
* @param array $form_state
*   Form API form.
*
* @return array
*   Form array.
*/
function newsletter_abz_wizard_callback($form, $form_state) {
  return $form;
}

/

*
* In AJAX this is only submitted when the final submit button is clicked,
* but in the non-javascript situation, it is submitted with every
* button click.
*/
function newsletter_abz_wizard_submit($form, &$form_state) {

  // Save away the current information.
  $current_step = 'step' . $form_state['storage']['step'];

  if (!empty($form_state['values'][$current_step])) {
    $form_state['storage']['values'][$current_step] = $form_state['values'][$current_step];
  }

  // Increment or decrement the step as needed. Recover values if they exist.
  if ($form_state['triggering_element']['#value'] == t('Next step')) {
    $form_state['storage']['step']++;
    // If values have already been entered for this step, recover them from
    // $form_state['storage'] to pre-populate them.
    $step_name = 'step' . $form_state['storage']['step'];
    if (!empty($form_state['storage']['values'][$step_name])) {
      $form_state['values'][$step_name] = $form_state['storage']['values'][$step_name];
    }
  }
  if ($form_state['triggering_element']['#value'] == t('Previous step')) {
    $form_state['storage']['step']--;
    // Recover our values from $form_state['storage'] to pre-populate them.
    $step_name = 'step' . $form_state['storage']['step'];
    $form_state['values'][$step_name] = $form_state['storage']['values'][$step_name];
  }
  // If they're done, submit.
  if ($form_state['triggering_element']['#value'] == t('Save Campaign')) {
    $value_message = t('Your information has been submitted:') . ' ';
    foreach ($form_state['storage']['values'] as $step => $values) {
      $value_message .= "$step: ";
      foreach ($values as $key => $value) {
        $value_message .= "$key=$value, ";
      }
    }
    drupal_set_message($value_message);
    $form_state['rebuild'] = FALSE;
    return;
  }

  // Otherwise, we still have work to do.
  $form_state['rebuild'] = TRUE;
}

Adicionalmente te he corregido la función get_nodes para que no ejecute un db_query, es más conveniente usar db_select que filtra la entrada, si usas db_query debes usar placeholders.

Muchas gracias!

nicoksq's picture

Gracias, ahora si funciona a la perfeccion. desconocia el tableselect! y gracias por lo de la query y el toque a los input de date, quedo mucho mejor ahora!.
Ahora, te molesto con otra consulta y lo termino, si quisiera paginar el resultado, tengo que hacer un desarrollo con la query, o drupal ya trae algo para eso?

Realmente muchas gracias!

Saludos

Paginador

jncruces's picture

Anteriormente no he realizado paginadores con tableselect debido a que no suele ser común que los usuarios tengan que seleccionar tantos elementos, es más, te recomendaría que lo tuvieras en cuenta, pues un paginador, con selects te va a ser dificil de manejar o le va a ser dificil de manejar a los potenciales usuarios. En mi opinión quizás te resultaría mejor poner filtros en la tabla de forma que puedas filtrar contenidos entre fechas más cortas y limitar la salida de alguna forma.

Una solución muy sencilla sería añadir los filtros de fecha en la misma página que la tabla y un select con las páginas y con el #ajax configurado para que recarguen el div del tableselect.

Si quieres seguir pensando sobre tu solución inicial he encontrado esto:
https://www.drupal.org/node/1365736

Saludos.

Spanish

Group organizers

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds:

Hot content this week