Chamadas AJAX no CTools Content Type Plugin?


10

Estou criando um tipo de conteúdo de painéis do CTools (ou seja, aquela coisa que você insere nos painéis ao adicionar conteúdo, não um tipo de nó) e estou tentando usar o #ajaxatributo de um item de formulário para definir alguns valores padrão. Veja o código abaixo.

A my_module_content_type_edit_form($form, &$form_state)propósito, tudo isso está dentro da chamada do tipo de conteúdo .

  $form['link_type'] = array(
    '#type' => 'radios',
    '#title' => t('Link Type'),
    '#ajax' => array(
      'callback' => 'my_module_set_target'
    ),
    '#default_value' => empty($conf['link_type']) ? '_blank' : $conf['link_type'],
    '#options' => array('none'=>t('No Link'), 'internal'=>t('Internal Link'), 'external'=>t('External Link'), 'document'=>t('Document Link')),
  );

Meu retorno de chamada é o seguinte.

function my_module_set_target($form, $form_state) {
  watchdog("Test", "Testing callback", array(), WATCHDOG_ALERT);
  $form['link_target']['#default_value'] = '_parent';

  return $form['link_target']['#default_value'];
}

Independentemente de o retorno que estou sugerindo realmente funcionar, watchdog()nem funciona.

Eu sei que o CTools faz algumas coisas estranhas com o AJAX, mas não pode ser tão estranho assim. Você tem alguma idéia de como eu faria o que estou querendo fazer?

Obrigado!

Como alternativa: como definir um valor padrão com base no valor de uma opção de formulário anterior?

Eu descobri como fazer isso, mas é um pouco hacky - você cria novos campos de formulário para cada fork de dependência. Em seguida, é possível mesclar os valores hook_content_type_edit_form_submit(), usando o que corresponder ao valor escolhido para o componente que inicialmente bifurcou tudo.

Estou deixando a pergunta em aberto porque eu (e, francamente, todos os programadores com os quais estou trabalhando) realmente deseja uma boa maneira de usar o AJAX dentro desses formulários de edição do tipo de conteúdo do Painel.

Atualização: parece que você também não pode fazer coisas com #attached.

$form['link'][$i] = array(
  '#type' => 'fieldset',
  '#title' => t('Link #@num', array('@num' => $i)),
  '#collapsible' => TRUE,
  '#collapsed' => TRUE,
  '#attached' => array(
    'js' => array(
      'alert("Yay.");', 'inline'
    ),
  )
);

Sendo um desenvolvedor de Drupal do tipo "Painéis para tudo", imagino que poderia encontrar utilidade para isso também no futuro, então adicionei uma recompensa e vamos ver o que acontece.
Letharion 17/08/12

Uau, essa recompensa veio e foi sem sequer um comentário (Obrigado, BTW, Letharion). O que estou pedindo é impossível ou algo assim?
aendrew

Vale a pena notar que eu consegui adicionar Javascript com sucesso usando ctools_add_js();ou drupal_add_js();no final de hook_content_type_edit_form();. Se você está apenas fazendo coisas simples relacionadas à interface do usuário, parece que essa é a melhor opção (pelo menos até alguém responder adequadamente a essa pergunta).
aendrew

Respostas:


8

Resposta curta: você deve usar #ajax ['caminho'].

Resposta longa:

Ter um retorno de chamada ajax não ajuda, pois o ctools cria seus formulários de maneira diferente. O retorno de chamada feito pelo system / ajax não pode encontrar a definição completa do formulário, portanto, não pode encontrar um elemento para processar a solicitação do ajax. O uso de #ajax [path] apenas aciona um item de menu.

Você pode verificar por si mesmo descartando o formulário ao usar #ajax [retorno de chamada]

function ajax_form_callback() {
  list($form, $form_state) = ajax_get_form();
  drupal_process_form($form['#form_id'], $form, $form_state);

Modifiquei o simplecontext_content_type_edit_form adicionando o widget de preenchimento automático do usuário e seu campo, os quais funcionam :)

function simplecontext_content_type_edit_form($form, &$form_state) {
  $conf = $form_state['conf'];

  $form['owner_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Username'),
    '#default_value' => 'admin',
    '#autocomplete_path' => 'user/autocomplete',
    '#size' => '6',
    '#maxlength' => '60',
    '#description' => '$description',
  );

  $form['link_type'] = array(
    '#type' => 'radios',
    '#title' => t('Link Type'),
    '#ajax' => array(
      'path' => 'my_module_set_target'
    ),
    '#default_value' => empty($conf['link_type']) ? '_blank' : $conf['link_type'],
    '#options' => array('none' => t('No Link'), 'internal' => t('Internal Link'), 'external' => t('External Link'), 'document' => t('Document Link')),
  );
...

Agora que você usa o caminho #ajax, precisa adicionar um item de menu como eu queria

<?php

function my_module_menu() {
  $items = array(
    'my_module_set_target' => array(
      'title' => 'AJAX Example',
      'page callback' => 'my_module_set_target',
      'access callback' => TRUE,
      'expanded' => TRUE,
    )
  );
  return $items;
}

function my_module_set_target() {
  drupal_json_output( array('data' => "ABC"));
}

Uma dica sobre #attached [js]: os js inline devem ser key => value como:

'#attached' => array(
  'js' => array(
    'alert("Yay.");' => 'inline',
  ),
),

Eu usei o Firebug para verificar o valor resultante e não o efeito resultante. Espero que isso ajude a resolver seu problema.


Uau. Estou muito feliz por finalmente ter uma resposta para esta pergunta. Vai experimentar daqui a pouco. Obrigado também pela observação no bit #attached, na verdade foi o que eu tinha inicialmente (mas mudei porque achei que não podia estar certo).
aendrew

Então, algum sucesso? Seria interessante saber antes que a recompensa acabasse :)
Letharion

Espero conseguir minha recompensa: p
Clemens Tolboom 6/06

Desculpe o atraso com isso, demorando um pouco para fazê-lo funcionar - quando tento retornar a matriz $ form, ele diz que minha função de validação não está definida. É, e quando tento declará-lo novamente no meu módulo (em oposição ao arquivo de plug-in do tipo de conteúdo), ele diz que estou redeclarando-o. Suponho que não é isso que preciso fazer, mas não consigo descobrir como estruturar drupal_json_output para que ele produza algo que meu formulário interpretará como uma resposta significativa. Qualquer ajuda? Um exemplo melhor de retorno de chamada ajudaria muito. Obrigado!
precisa saber é

Perdi a pequena parte da sua pergunta que é sobre o valor de retorno : return $ form ['link_target'] ['# default_value']; que é sua tentativa de retornar um formulário drupal para um contexto html / javascript . Isso não vai funcionar. Você já viu algo semelhante ao que deseja na interface do usuário dos painéis? (Eu mesmo desativar JavaScript agora e, em seguida, com vistas UI só para ver os não js Workflow) (editado este comentário um zilhão de vezes ... desajeitados)
Clemens Tolboom

2

Eu tive um problema semelhante, no qual queria incluir um tipo de elemento de mídia em um plug-in de tipo de conteúdo do CTools, que também usa o ajax para selecionar uma imagem.

Ele usa sua própria configuração de 'caminho' do ajax, em vez da configuração de 'retorno de chamada', mas ao selecionar uma imagem, o formulário foi reconstruído sem o elemento de mídia completamente.

Rastreei isso pelo fato de que drupal_rebuild_form não pôde encontrar nem a função wrapper de formulário CTools nem a função de formulário de configurações reais. Então eu o corrigi adicionando essas linhas de código ao formulário de configurações do ctools:

function custom_module_my_content_plugin_content_type_edit_form($form, &$form_state) {

$background_image = isset($conf['background_image']) ? $conf['background_image'] : array();
  $form['background_image'] = array(
    '#title' => t('Background image'),
    '#default_value' => $background_image,
    '#type' => 'media',
    '#input' => TRUE,
    '#extended' => TRUE,
    '#tree' => TRUE,
    '#media_options' => array(),
  );

  // The two function calls below are necessary if we want to use a media
  // element type, because it causes ajax requests, which in turn call
  // drupal_form_rebuild(), and without the below includes, Drupal will
  // not be able to rebuild the form.

  // Include the CTools content type plugin file, because it provides
  // the ctools_content_configure_form_defaults() function, which is needed
  // when rebuilding the form, because of an ajax action, like selecting
  // a media element.
  ctools_form_include($form_state, 'content');

  // Include this plugin file as well, so that when the form is rebuilt, it
  // can successfully retrieve the settings form.
  ctools_form_include($form_state, 'my_content_plugin', 'custom_module', 'plugins/content_types/my_content_plugin');

}

Talvez esteja faltando algo óbvio por que os arquivos de inclusão não foram carregados, mas incluí-los manualmente corrigiu o problema para mim.


0

do meu lado, tive que escrever uma função de wrapper de formulário no arquivo .module e incluir o painel manualmente (onde o conteúdo do formulário original é definido) assim:

function mymodule_form($form, &$form_state) {
  // include mymodule/panes/mypane.inc
  ctools_include('mypane', 'mymodule', 'panes');
  return mymodule_form_content($form, $form_state);
}

Agora, durante a chamada ajax, o Drupal pode recuperar meu formulário para que eu possa usar a API de formulário padrão AJAX.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.