Hi
With D7 the #attached property is the correct way to add javascript/css to ensure that our files are always loaded even with cached output however the way to add javascript settings is not evident from http://api.drupal.org/api/drupal/developer--topics--forms_api_reference....

Whilst one can figure it out if they read up on drupal_process_attached a clear example would help.
The attached patch adds a new example of how to add js settings using attached.

Comments

larowlan’s picture

Status: Active » Needs review
StatusFileSize
new1.25 KB
jhodgdon’s picture

We need someone with more Drupal JavaScript knowledge than me to review this. I'll see who I can round up.

rfay’s picture

@larowlan, I apologize for how hard it is to work with this doc, and it looks to me on a casual look like your patch is great..

But could you do me a favor in the future? Could you please put the old and the new markup into the issue here, so it can be reviewed without having to clone the project and apply the patch and then look at it in a browser?

Here's what I'm intending:

Existing

Usage example (AJAX Example):

$form['#attached']['css'] = array(<br/>
  drupal_get_path('module', 'ajax_example') . '/ajax_example.css',<br/>
);<br/>
$form['#attached']['js'] = array(<br/>
  drupal_get_path('module', 'ajax_example') . '/ajax_example.js',<br/>
);<br/>

The above javascript #attach could also be written as:

$form['#attached']['js'] = array(<br/>
&nbsp;&nbsp;drupal_get_path('module', 'ajax_example') . '/ajax_example.js' => array(<br/>
&nbsp;&nbsp;'type' => 'file',<br/>
&nbsp;&nbsp;),<br/>
);<br/>

and inline javascript can be loaded with the javascript as the key of the array,
as described in drupal_add_js()

New (with patch)

Usage example (AJAX Example):

$form['#attached']['css'] = array(<br/>
  drupal_get_path('module', 'ajax_example') . '/ajax_example.css',<br/>
);<br/>
$form['#attached']['js'] = array(<br/>
  drupal_get_path('module', 'ajax_example') . '/ajax_example.js',<br/>
);<br/>

The above javascript #attach could also be written as:

$form['#attached']['js'] = array(<br/>
&nbsp;&nbsp;drupal_get_path('module', 'ajax_example') . '/ajax_example.js' => array(<br/>
&nbsp;&nbsp;'type' => 'file',<br/>
&nbsp;&nbsp;),<br/>
);<br/>

and inline javascript can be loaded with the javascript as the key of the array,
as described in drupal_add_js()

Adding settings

You add a javascript setting by using the 'data' key (as php keys can't be arrays):

$settings = array('id' => 'mymodule-element-1');<br />
$form['#attached']['js'][] = array(<br/>
&nbsp;&nbsp;'data' => array('mymodule' => $settings),<br/>
&nbsp;&nbsp;'type' => 'setting',<br/>
);<br/>

Wow, the codefilter on api must be different from the one here. Oh well, at least this way it's easy to get the gist of it.

rfay’s picture

Status: Needs review » Reviewed & tested by the community

This looks right to me. Thanks!

larowlan’s picture

Thanks Jennifer and Randy.
@rfay - will do regarding example next time.

jn2’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs backport to D7 +FAPI reference

I've added the new example to the FAPI reference. Thanks, larowlan!

Status: Fixed » Closed (fixed)

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

stefan freudenberg’s picture

Status: Closed (fixed) » Active

Hi.

Sorry for reopening, but I believe this documentations needs to be improved. Although it is correct it leads people to overwrite existing attached items in form alter hooks. In my opinion the documentation should recommend to add elements to the attached keys by appending them, i.e. $form['#attached']['js'][] etc. If you agree I'll provide a patch.

Best,
Stefan

jhodgdon’s picture

Stefan: That is definitely the correct recommendation. If you have a suggestion on how to make the documentation say that more clearly, especially if your suggestion comes in the form of a patch, then this would be most welcome. :)

We probably need one patch for Drupal 8.x/7.x, and another for 6.x... oh wait, #attached doesn't exist in 6.x. So, just a patch for 7.x (which will presumably also apply just fine to 8.x) would be great. Thanks!

wizonesolutions’s picture

I might be able to do this - I got a bit confused by the same thing, thinking, "Wait, so I'm overriding the Node module's attached JS potentially?"

To confirm, do I clone the documentation project and patch the HTML file in developer/topics?

jhodgdon’s picture

Yes, that's the file to patch -- start with the 8.x repository (even though we don't have a way to set the version on this project, since it's mostly for issues with on-line docs pages). Thanks!

j0rd’s picture

Appears the information related with how to use this field in D7 is in-correct, or at least not as correct as it should be.

A proper example for D7 should be


$form['#attached']['js'][] = drupal_get_path('module', 'ajax_example') . '/ajax_example.js';

// The above javascript #attach could also be written as:

$form['#attached']['js'][] = array(
  'data' => drupal_get_path('module', 'ajax_example') . '/ajax_example.js',
  'type' => 'file',
  'weight' => 0,
  );

The whole #attached section in the field api documentation actually requires a full re-write to be clear and concise. Judging by the amounts of incorrect example snippets on the internet, I suspect this documentation is to blame.

nick_schuch’s picture

Status: Active » Needs review
StatusFileSize
new1.07 KB

I have included a patch which provides a "scope" setting example for #attached.

grendzy’s picture

StatusFileSize
new887 bytes

This text is also incorrect:

You add a javascript setting by using the 'data' key (as php keys can't be arrays)

The key must be numeric. This can be seen in the source for drupal_process_attached(): The is_numeric() function is used to detect attached settings data.

MauMau’s picture

Hope this helps someone.

Three ways to attach a script to a field.

$script = get_user_data_as_js_script();
      
      $form['field_use_my_info']['#attached'] = array (
          'js' => array(
// Attaching a js script file
            'misc/ui/jquery.ui.core.min.js',
// Attaching a js script from a file and putting it in the footer
            drupal_get_path('module', 'manipulate_user') . '/manipulate_user.footer.js' => array('type' => 'file', 'scope' => 'footer', 'weight' => 101),
// Attaching a js script inline
            $script => array( 'type' => 'inline'),
            ),
      );
jhodgdon’s picture

Status: Needs review » Needs work

Ummm... but there *is* a data key in there. I don't think the patch in #14 is needed or that it clarifies anything. Yes, the outer key is numeric, but the inner one in the example is 'data'.

And I don't think the patch in #13 resolves the issue that was brought up in previous comments.

grendzy’s picture

Yeah, you're right that my patch in #14 is not helpful. The problem is there are 4 different ways to construct an #attached array. In the first three, the $data parameter can be stored in either the array key, the array value, or the 'data' value nested inside the options array. (It's okay if your head just exploded, mine did too.)

Here are the 4 ways, using variable names that match the drupal_add_* function parameters.


// Method 1, JS or CSS
$element['#attached']['js'][] = $data; // This is assumed to be a local file name. JS or CSS


// Method 2, JS or CSS
$element['#attached']['js'][$data] = $options; // $data can be an external URI, a local file, or inline code.


// Method 3, JS or CSS.  JS settings *must* use this version.
$options['data'] = $data; // $data can be any type
$element['#attached']['js'][] = $options; // Brackets must be empty, or contain a numeric index


// Method 4, libraries are special
$element['#attached']['library'][] = array(
  $module,
  $name,
);

Seeing it in this format helps to understand the relationship with the drupal_add_* functions, but lacks working examples. So I think maybe we actually need 8 code snippets in the doc; the 4 above followed by 4 examples.

I'm also a little sad it's too late to simplify this construct in D8.

bdimaggio’s picture

Issue summary: View changes

@grendzy, this snippet is hugely helpful in illuminating the #attached form element property. Thanks!

quietone’s picture

Status: Needs work » Closed (won't fix)

Thanks for working to improve Drupal.

This is for the Drupal 7 Form API reference. Since Drupal 7 is past end-of-life this is now a "won't fix".

Work on documentation for form elements for supported versions of Drupal is at #2486967: [meta] Move/Create Form Element Documentation and #3313535: [Meta] Improve documentation for Render and Form Elements.