Programmatically adding columns in VIEWS - drupal

In drupal 7 view, I have created a custom module and add dynamic columns using below method.
function my_module_views_pre_view(&$view, &$display_id, &$args) {
if ($view->name == 'my_view') {
$countries = my_module_vocab_terms('countries');
foreach ($countries as $country){
$view->add_item($view->current_display, 'field', 'views', 'nothing', array(
'label' => $country->name,
'alter' => array('text' => $country->tid),
'element_class' => 'my-field',
'element_default_classes' => 0,
), $country->tid);
}
}
}
}
But the text value repeated in each rows like this.
Please suggest how to pass value for each row.
Thanks

If anyone is still interested how to alter values to such fields.
You can do so by rendering the fields and altering the data in one of the hooks where the results are already fetched eg. the hook_views_post_execute, hook_views_pre_render, hook_views_post_render depending on your needs.
/**
* Implements hook_views_post_execute().
*/
function my_module_views_post_execute(view &$view) {
$view->style_plugin->render_fields($view->result);
$view_fields = &$view->style_plugin->rendered_fields;
foreach ($view_fields as &$field) {
$field['my_field'] = "some value";
}
unset($field);
}

Related

Drupal 8 translating paragraphs programmatically

Paragraphs are supposed to be translated on on the level of their component fields, not on the paragraph_field level. So how do you programmatically translate paragraphs?
To be more explicit, my paragraph field is not translatable, but the component fields are. So how can I load a node, loop through the paragraph items, and add translations to the fields?
Does anyone have an example?
Thanks.
following https://www.flocondetoile.fr/blog/translate-programmatically-drupal-8 node translation:
This is an abstraction of my actual code, and I haven't actually tested it:
$node = node_load(12);
if ($node->hasTranslation('de')) {
$transl_node = $node->getTranslation('de');
foreach ($transl_node->field_paragraph => $paragraph) {
$entity_array = $paragraph->toArray();
$translated_fields = [];
$translated_fields['field_body'] = array(
'value' => 'translated value',
'format' => 'full'
);
$translated_fields['field_section_title'] = 'translated section title';
$translated_entity_array = array_merge($entity_array, $translated_fields);
if (!$paragraph->hasTranslation('de')) {
$paragraph->addTranslation('de', $translated_entity_array);
$paragraph->save();
}
}
$transl_node->save();
}

Symfony2 dynamically assign attr to form field

I'm in a situation where I want to be able to dynamically set the required=true/false option or the array(...other stuff..., 'class' => ' hidden') of a form field.
The context is the following: there is a "Project" entity with some fields. When I create other entities with forms I want to check some attributes of the Project entity and make decisions on the visibility/requiredness of certain fields of the entity I'm creating.
For example if a Project is with attribute "timePressure=high" then a field of a given entity is not required (but is visible). If there are other conditions it becomes invisible etc...
So basically I was hoping to call a function inside each ->add() of the form builder to spit out the relevant portions (e.g. that function would return a string with "required=true" or the other related to the hidden class). The thing is that the function should take as arguments: the projectID (ok, this can be passed as options of the form builder), the class and the field we are talking about to decide. I was envisioning something like:
->add('background', 'textarea', array('attr' => array('rows' => 4, functionToDecideIfInvisible($projectId)), functionToDecideRequiredness($projectId)))
The two function would return the string 'class' => ' hidden' and required=true (or false)
I'd like to avoid to having to specify the field name (in this case background) to avoid code repetition.
Can this be done?
Other suggestions on how to solve the thing?
Thank you!
SN
What you need are Form Events: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-underlying-data
They allow you to modify your form based on your data.
You create you project form in the controller:
$form = $this->createForm(new ProjectType(), $project, array(
'action' => $this->generateUrl('project.edit'),
'method' => 'POST',
));
Then you add the FormEvents::PRE_SET_DATA listener:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$project = $event->getData();
$form = $event->getForm();
// check timePressure on the Project object
if ('high' === $project->timePressure) {
$form->add('timePressure', 'text', array(
'required' => false
);
}
});
}
I found a way to do it.
My add would be like:
->add('background', 'textarea', array_merge($this->vr->fieldReq(get_class($this),
'background', $projectID), array('attr' => array_merge(array('rows' => 4, ),
$this->vr->fieldCssClass(get_class($this), 'background', $projectID) ) )))
To do that I had to define the form as service, plus I created another class as service (the one which holds the two methods I need).
This is the class:
class FieldReqAndCssClass
{
public function fieldReq($parentEntity, $field, $projectID)
{
$required = array();
$required['required'] = false; //do stuff on the database instead of setting it to false hardcoded
return $required;
}
public function fieldCssClass($parentEntity, $field, $projectID)
{
$cssClass= array();
//do stuff on the database instead of setting the class as hidden hardcoded
//$cssClass['class'] = ' hidden';
$cssClass['class'] = '';
return $cssClass;
}
}
Of course in my form I had to:
public function __construct(\AppBundle\Util\FieldReqAndCssClass $fieldReqAndCssClass)
{
$this->vr = $fieldReqAndCssClass; // vr stands for visibility and requiredness
}
And these are the two services:
app_bundle.field_req_and_css_class:
class: AppBundle\Util\FieldReqAndCssClass
arguments: []
app_bundle.form.type.projectdetail:
class: AppBundle\Form\Type\ProjectDetailFormType
arguments: [#app_bundle.field_req_and_css_class]
tags:
- { name: form.type, alias: ProjectDetail }
Of course here in the first service I'll need to inject the entity manager and add it to the construct, and probably also in the form service, but the basic skeleton is working :)
I'm a happy man :)
EDIT
The only problem of the above is that it makes hidden the widget but not the label. To fix it:
->add('background', 'textarea', array_merge($vr->fieldReq($myClass,
'background', $project), array('label_attr' => $vr->fieldCssClass($myClass,
'background', $project),'attr' => array_merge(array('rows' => 4, ),
$vr->fieldCssClass($myClass, 'background', $project) ) )))
Obviously before I have to declare:
$myClass = get_class($this);
$vr = $this->vr;

hook_form_alter, add hidden elements such as an array

How do you attach hidden elements, or values such an array to forms via hook_form_alter ?
I can access different parts of the form, but get error when trying to add a key or value.
Something like this should work:
function sample_module_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'FORM-ID') {
$form['sample_module_hidden_field'] = array(
'#type' => 'hidden',
'#value' => 'your-value',
);
$form['#submit'][] = 'sample_module_form_submit';
}
}
function sample_module_form_submit($form, &$form_state){
$values = $form_state['values'];
// store the value from the hidden field
if(!empty($values['sample_module_hidden_field'])){
variable_set('sample_module_hidden_field', $values['sample_module_hidden_field']);
}
}
You should change the FORM-ID to the id of the form you would like to alter. Also, of course you should alter the name and value of the field.
This is also a must read: Form API Reference

Drupal Admin form AJAX callback not working

I am trying to implement an AJAX callback to change a drop down list options based on the values of another drop down.I have looked into the examples online and the examples in the examples module. I am trying to implement the example on one of the admin pages forms.
To simplify, I tried to achieve the following: Just to change the title of the second dropdown with a random number once the first dropdown has changed. Please note that I am using a field collection field.
function myaction_form_alter(&$form, &$form_state, $form_id) {
$form['field_programme_permission']['und']['0']['field_programme']['und']['#ajax']=array(
'event' => 'change',
'callback' => 'programmes_ajax_callback',
'method' => 'replace',
'wrapper' => 'countries_wrapper'
);
$form['field_programme_permission']['und']['0']['field_countries']['und']['#title']=rand(1,100);
return $form;
}
function programmes_ajax_callback($form, $form_state) {
return $form['field_programme_permission']['und']['0']['field_countries'];
}
It is as if programmes_ajax_callback is not triggered at all. I see this Drupal AJAX please wait message but nothing actually happens. The weird thing, If I submit the form and it doesn't pass validation, I don't even see this Drupal AJAX "please wait" message. I have simplified the code as much as possible to try to pin point the problem, but it didn't work...
Any ideas?
The problem was caused by the fact that countries_wrapper didn't actually exist as I was actually calling it countries-wrapper somewhere else.
Find below the code that I have actually used. This code covers a muti-value (up to 10) field collection at which one field (countries) in the field collection is dependent on the other (programme). Hopefully, it will prove to be useful for someone.
function mymodule_form_alter(&$form, &$form_state, $form_id) {
for($i=0;$i<10;$i++) {
if(($form_id=='user_register_form') || ($form_id=='user_profile_form')) {
if(isset($form_state['values']['field_programme_permission'][LANGUAGE_NONE][$i]['field_programme'][LANGUAGE_NONE][0]['tid'])) {
$programme_selected= $form_state['values']['field_programme_permission'][LANGUAGE_NONE][$i]['field_programme'][LANGUAGE_NONE][0]['tid'];
} else {
$programme_selected=0;
}
if(isset($form_state['field']['field_programme_permission']['und']['entity'][$i]->field_programme['und'][0]['tid'])){
$programme_selected=$form_state['field']['field_programme_permission']['und']['entity'][$i]->field_programme['und'][0]['tid'];
}
$form['field_programme_permission'][LANGUAGE_NONE][$i]['field_programme'][LANGUAGE_NONE]['#ajax']=array(
'event' => 'change',
'callback' => '_programmes_ajax_callback',
'method' => 'replace',
'wrapper' => 'countries_wrapper'.$i
);
$form['field_programme_permission'][LANGUAGE_NONE][$i]['field_countries'][LANGUAGE_NONE]['#title']='Countries';
$form['field_programme_permission'][LANGUAGE_NONE][$i]['field_countries'][LANGUAGE_NONE]['#prefix']='<div id="countries_wrapper'.$i.'">';
$form['field_programme_permission'][LANGUAGE_NONE][$i]['field_countries'][LANGUAGE_NONE]['#suffix']='</div>';
$form['field_programme_permission'][LANGUAGE_NONE][$i]['field_countries'][LANGUAGE_NONE]['#options']=_countries_ajax_callback($programme_selected);
}
}
return $form;
}
function _programmes_ajax_callback($form, $form_state) {
//we first need to know the triggering element, to know the index of the countries field that we need to affect.
$index= $form_state['triggering_element']['#field_parents'][2];
return $form['field_programme_permission'][LANGUAGE_NONE][$index]['field_countries'];
}
function _countries_ajax_callback($selected) {
$programme_value = $selected;
$options=array();
if(taxonomy_term_load($programme_value)){
$programme_taxonomy=taxonomy_term_load($programme_value);
if(isset($programme_taxonomy->field_countries[LANGUAGE_NONE])) {
$countries=$programme_taxonomy->field_countries[LANGUAGE_NONE];
foreach($countries as $country) {
$country_tid = $country['tid'];
$country_term = taxonomy_term_load($country_tid);
$country_name = $country_term->name;
$options[$country_tid]=$country_name;
}
}
}
return $options;
}

Change field using theme_preprocess_field()

gunwinner is my theme name and i want to change a field on particular content type.
I have tried this code,
function gunwinner_preprocess_field(&$variables) {
$element = $variables['element'];
if($element['#field_name'] == 'field_deal_url') {
$values = $element['#items'][0]['value'];
$deal_link = l(t("Go to Store"), "$values", array('attributes' => array('class' => 'store-link')));
$element['#items'][0]['value'] = "Store";
return;
}
}
which returns me the array with the link title "Go to Store" but it doesn't reflect on the page for the particular field.
Can anyone help me out for this?
You're making a copy of $variables['element'] and manipulating that, so the changes aren't being persisted into the original variable.
Just change the first line of your function to
$element = &$variables['element'];

Resources