3

I have some menus that are managed in the standard Menus module (Drupal 6, BTW). I want to add a checkbox when I'm editing a menu item to control the display of a "New" banner via CSS (by adding a class for items that have the checkbox turned on).

I can get my checkbox into the form like so:

function mymodule_form_menu_edit_item_alter(&$form, &$form_state) {
  $form['menu']['newbanner'] = array(
    '#title' => 'New banner',
    '#type' => 'checkboxes',
    '#description' => "Add a 'New' banner to this item?",
    '#options' => array( 'new_banner' => t("This item is new") )
    );
}

But I'm not quite sure how to actually save and use the state of my checkbox. I'm guessing I want to start by creating a mymodule_form_menu_edit_item_submit() function? But how do I get my info in/out of the database and use it to add a class to the generated menu on the front-end?

2
  • More specifically, should I use the variable table to store my checkbox state, or is that bad form? Commented Mar 21, 2011 at 17:24
  • Saving the value into your own Drupal variable is correct; it is what I would do, and it is the only alternative to using your own database table, which is a little excessive, in this case.
    – avpaderno
    Commented Mar 21, 2011 at 18:00

3 Answers 3

3

The code you wrote so far is correct; you just need to add the code for getting the saved setting, and the code to save it.

function mymodule_form_menu_edit_item_alter(&$form, &$form_state) {
  // Get the mlid ID of the menu item.
  $mlid = $form['menu']['mlid']['#value'];

  $form['menu']['newbanner'] = array(
    '#title' => 'New banner',
    '#type' => 'checkboxes',
    '#description' => "Add a 'New' banner to this item?",
    '#default_value' => variable_get("mymodule_newbanner_$mlid", 0),
    '#options' => array('new_banner' => t("This item is new")),
  );

  $form['#submit'][] = 'mymodule_menu_item_submit';
}

function mymodule_menu_item_submit($form, &$form_state) {
  $item = &$form_state['values']['menu'];
  // Get the last ID inserted in the table.
  if (empty($item['mlid'])) {
    $item['mlid'] = db_last_insert_id('menu_links', 'mlid');
  }

  variable_set('mymodule_newbanner_' . $item['mlid'], $item['newbanner']);
}

The mlid could be zero, when the menu item is first created; in that case, the form submission handler gets it from the table, as it is executed after the form submission handler added by menu.module, which saves the menu item in the table using menu_link_save().

3
  • Thanks, that works great for saving the state in the form for editing a menu item. But I think it might be a performance killer on the front-end when I'm generating my menu. This module (inherited code) is bypassing the regular theming, and looping over the menu link structure. Using the mlid as part of the key, as you did above, won't I have to test for its existence for each menu item in our navigation? Wouldn't I be better off using a single key, and storing a data-structure containing all menu items which have the flag set? Commented Mar 21, 2011 at 19:09
  • The value of mlid is set for each menu item; I don't think that checking that value is a performance killer, if you get the menu structure from Drupal. Depending on what you need to do, you can use the value of pid, but in that case the setting would be for each parent menu, not for the single menu item. As far as I know, to check the value of mlid is the quicker way to identify a menu item; it is always better than to check the menu item title, which could be changed.
    – avpaderno
    Commented Mar 21, 2011 at 19:33
  • I'm going to go ahead and flag this as answered, though I'm still working on solving it completely. The problem I'm having now is that for some reason, the mlid isn't showing up on my menu items that have sub-menus. When I get it working completely, I'll try to get a pointer up to the final solution. Commented Mar 25, 2011 at 12:44
0

Please, please, please do not add your row-level data to the variables table. The entire variables table is cached and loaded on every page, adding to the memory footprint of each page request.

In this case, a variable would be created for every menu item that is saved, which could quickly add up. Though this individual case may not add up to that much extra data, imagine if many modules used the variables table as a data dumping ground.

As a general rule of thumb, if your data has multiple rows, you should probably use a separate table.

1
  • I reworked the example above so that I only needed to save one variable, which contained an array of menu item IDs to match against. Commented Mar 25, 2011 at 11:54
0

You may want to have a look at the Menu attributes module.

This will allow you to set various additional attributes on your menu items including classes and ids which you can then target with css or jquery.

Some more details about this module (from its project page):

This simple module allows you to specify some additional attributes for menu items such as id, name, class, style, and rel.

You should use this module when

  • You want to "nofollow" certain menu items to sculpt the flow of PageRank through your site
  • You want to give a menu item an ID so you can easily select it using jQuery
  • You want to add additional classes or styles to a menu item

The module currently allows you to set the following attributes for each menu item:

  • Id
  • Name
  • Target
  • Rel
  • Class
  • Style
  • Accesskey
1
  • Thanks for pointing that one out. In this case, I prefer to solve the problem on my own, as a learning experience, if nothing else. But I will definitely look at how the Menu Attributes module approaches things. Commented Mar 25, 2011 at 12:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.