Custom Drupal Elements for Forms

Posted on July 9, 2013

One of the most cryptic tasks in Drupal is defining a custom form element. That is, defining your own element types to be used and resused in your forms. This post will walk you through the basics. And there's no better way than to learn by example.

For our example element, let's define one that links to a github or bitbucket repository. These two sites host a lot of open source projects, so it makes sense to have an element that handles both. Note: this guide applies to Drupal 7. You should be able to make it work on Drupal 6 with some minor modifications. Let's call our element gitbucket.

Learning Drupal? Subscribe to my Drupal articles, tips and tutorials.

![3]

Part of what makes the Form API in Drupal so powerful is that we can define compound custom elements. In other words, elements that contain one or more existing elements. This is quite useful for our use case, where we want our gitbucket field to have both, a source field (github or bitbucket) and a username/repository field. So let's get started.

The key to creating a custom element is hook_element_info(), where we provide information about our element. So let's define it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<?php

function example_element_info() {
  $elements['gitbucket'] = array(
    '#default_value' => '',
    '#input' => TRUE,
    '#process' => array('example_gitbucket_element_process'),
    '#theme' => array('gitbucket_field'),
    '#theme_wrappers' => array('form_element'),
    '#tree' => TRUE,
    '#value_callback' => 'example_gitbucket_element_value_callback',
  );
  return $elements;
}

As you can see above, we're providing the Form API with quite a bit of info. Let's walk through this hook step by step.

Our #process callback is what gets called when we're going to use the element in a form. This is where we turn our element from a simple definition into the compound element that we want. So we provide a callback function for it. We'll get to that in a bit.

We also define a #theme callback. This is what renders the inside of our element, including the subelements that we'll define. We have a lot of flexibility here when rendering. Using this callback, we'll make sure our element looks nice and readable.

Next we provide #theme_wrappers. As you'd imagine, this wraps all the elements after they come back from the #theme callback. Generally, you can just use the built-in form_element and let it do the work for you. That's exactly what we're doing here.

Last but not least, we define #tree and #value_callback. The first makes sure our nested element structure is preserved for our values, rather than flattened. The second provides a way to process values before they are returned to the form submit function. You need to provide a #value_callback if you want to do fancy processing on the input.

With all of that declared, we can now implement our #process function to construct our very own custom element:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php

function example_gitbucket_element_process($element, $form_state, $complete_form) {

  $element['gitbucket']['source'] = array(
    '#type' => 'select',
    '#empty_option' => '- ' . t('Source') . ' -',
    '#options' => array(
      'github' => 'github://',
      'bitbucket' => 'bitbucket://',
    ),
    '#required' => $element['#required'],
    '#title' => t('Repository Source'),
    '#title_display' => 'invisible',
    '#theme_wrappers' => array(),
  );

  if (isset($element['#default_value']['gitbucket']['source'])) {
    $element['gitbucket']['source']['#default_value'] = $element['#default_value']['gitbucket']['source'];
  }

  $element['gitbucket']['address'] = array(
    '#type' => 'textfield',
    '#size' => 50,
    '#required' => $element['#required'],
    '#title' => t('Repository Name'),
    '#title_display' => 'invisible',
    '#theme_wrappers' => array(),
    '#attributes' => array('placeholder' => 'username/repository'),
  );

  if (isset($element['#default_value']['gitbucket']['address'])) {
    $element['gitbucket']['address']['#default_value'] = $element['#default_value']['gitbucket']['address'];
  }

  return $element;
}

As you can see, we're nesting elements in the snippet above. Our custom element consists of a select field for the repository source, and a textfield for the actual repository. The actual declaration of these fields is straightforward, and you can use almost anything in the Form API.

When nesting elements, there are a couple of quirks to watch out for. First, you probably don't want a bunch of nested titles shown. That's why we set #title_display to invisible. But we still declare a title for error handling purposes. We want the Form API to be able to pinpoint fields required nested fields and the like.

You also don't want the wrapping HTML structure around each individual nested element. You want it outside the entire compound element. So for each nested element, we set #theme_wrappers to an empty array.

And that's it. We load up default values as necessary, and we're done processing our custom elemenet. Let's move on to theming.

We want a nice inline look for our field, so let's keep the theming simple. First we need to register our function, and then implement it. Like so:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?php

function example_theme() {
  return array(
    'gitbucket_field' => array(
      'render element' => 'element',
    ),
  );
}

function theme_gitbucket_field($variables) {
  $element = $variables['element'];
  $output = '';
  $output .= drupal_render($element['gitbucket']['source']);
  $output .= " "; // This space forces our fields to have a little room in between.
  $output .= drupal_render($element['gitbucket']['address']);
  return $output;
}

Now we're ready for the last part: the value callback. As you can see, our custom element has two parts. You should select either or none. But what happens if they just select a source with no repository name? If we marked the field as required, Drupal handles that for us by requesting both fields be populated. The problem appears when our field is not marked as required. In this case, if we fill just one and not the other, we want to treat this as the user having left the field empty. We can use the value callback for this 1.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?php

function example_gitbucket_element_value_callback($element, $input = FALSE, &$form_state) {
  if ($input !== FALSE) {
    if ($input['gitbucket']['source'] && !$input['gitbucket']['address']) {
      $input['gitbucket']['source'] = '';
    }
    if ($input['gitbucket']['address'] && !$input['gitbucket']['source']) {
      $input['gitbucket']['address'] = '';
    }
    return $input;
  }
  elseif (!empty($element['#default_value'])) {
    return $element['#default_value'];
  }

  return;
}

Value callbacks should be divided into three conditions:

  1. Input is being provided directly. This happens when a form is submitted.
  2. No input is provided, but the field definition has a default value.
  3. No input is provided and there is no default value.

In the first part, we handle the edge case of partial input. If only half the field is filled out, we simply treat it as empty. Then we return the modified input.

And that's it. You're done. You've now defined a custom compound field that can be used in any Drupal forms. For example, let's declare a simple system settings form that uses our newly minted element.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php

function example_form() {
  $form = array();
  $form['required_field'] = array(
    '#type' => 'gitbucket',
    '#title' => t('Your favorite repository'),
    '#required' => TRUE,
    '#default_value' => variable_get('required_field', array()),
  );
  $form['optional_field'] = array(
    '#type' => 'gitbucket',
    '#title' => t('Your least favorite repository'),
    '#default_value' => variable_get('optional_field', array()),
  );
  return system_settings_form($form);
}

Try it out. Fill in partial input and hit submit. You'll see how our fields behave properly even with missing input.


  1. Technically, you can also use validation hooks for this. 

Comments

Martin MaritimMarch 7, 2014, 7:31 a.m.

Very useful, thanks for posting this.

Reply
DacoAug. 4, 2017, 7:42 p.m.

шрифт - глаза сломать можно...

Reply
Cody SquiresMarch 15, 2019, 6:16 a.m.

Forms for the elements have different of the customs which will not be proceeding on the projects of the reused above there. Drupal have modification part of the best thesis editing services that will example of the resused terms.

Reply
dsdsdMay 6, 2019, 5:56 a.m.

Pour les nouveaux problèmes et les nouvelles choses rencontrées dans le processus de vente, nous pouvons analyser sérieusement, montblanc montres oser nous ouvrir et avancer avec audace nos propres idées et solutions; face aux situations d’urgence, nous devons rester calmes et rationnels, et essayer de résoudre les facteurs défavorables, ne paniquez pas. Main et pied, action impulsive. La résilience reflète la confiance en soi, la sagesse et l'optimisme d'une personne. À cause du même problème, les personnes passives et pessimistes choisissent de fuir et d'abandonner, ne prennent jamais l'initiative de réagir, tandis que les personnes positives et optimistes avancent, omega montres n'abandonnent jamais et enfin surmontent les obstacles.

Reply
fggfggfMay 18, 2019, 2:22 p.m.

Il y a beaucoup de vendeurs qui ont des malentendus dans leur compréhension, la plupart aiment toujours parler en fonction de leurs propres idées ou de la façon dont ils aiment. Par exemple, quand un vendeur voit un client, nous continuons à le présenter: nous disons toujours que nos produits sont différents et que nous pouvons apporter beaucoup d’avantages à nos clients, car ils sont plus populaires que les produits similaires. Malheureusement, les clients ne veulent pas écouter cela. Même si vous le dites bien, cela ne jouera pas un rôle passionnant, montre lamborghini replique mais les clients se sentiront ennuyés. Par conséquent, avant que le vendeur n'ouvre la porte, il devrait d'abord se demander si le client est prêt à l'écouter, sinon, le client se sentira heureux, sinon ce sera en vain.

Reply
Walter D. SmithMay 21, 2019, 10:21 a.m.

Hi! I require custom form in my cheap assignment services website. So please propose any module or can without coding conceivable make in custom structure?

Reply
Online Quran academyJune 19, 2019, 7:01 a.m.

We are innovative so we teach online and offer you the best learning practice https://www.iqraqurancenter.com/

Reply
harisJune 27, 2019, 12:25 p.m.

1st

[url="https://www.google.com/"]2nd[/url]

[url=https://www.google.com]3rd[/url]

[https://www.google.com 4th]

5th

"6th":https://www.google.com/

[A=https://www.google.com/]7th[/A]

Reply
muneer ahmedJuly 10, 2019, 7:38 a.m.

I want you to thank for your time of this wonderful read!!! médium téléphone I definitely enjoy every little bit of it and I have you bookmarked to check out new stuff of your blog a must read blog

Reply
muneer ahmedJuly 13, 2019, 6:08 p.m.

I am looking for and I love to post a comment that vraie voyance par sms "The content of your post is awesome" Great work

Reply
muneer ahmedJuly 16, 2019, 2:12 p.m.

Great job for publishing such a beneficial web site. cvv.me Your web log isn’t only useful but it is additionally really creative too. There tend to be not many people who can certainly write not so simple posts that artistically. Continue the nice writing

Reply
digitincJuly 27, 2019, 4:21 p.m.

Its a great pleasure reading your post. The information here Melanotan 2 10MGS surely be of some help to me. I just played upon your blog and wanted to say that I have really enjoyed reading your blog stations. Thanks for sharing.

Reply
PaverAug. 2, 2019, 1:24 p.m.

I really appreciate this excellent post that you Paver have provided for us. I found your website certain for my needs. I truly like what you have acquired here, really like what you’re saying and the way in which you say it. Thank you for sharing this article.

Reply
samAug. 7, 2019, 5:48 a.m.

Good post but I was wondering if you could write a litte more on this subject? I’d be very thankful if you could elaborate a little bit further. Appreciate it..! domino88

Reply
digitincAug. 8, 2019, 1:50 p.m.

This really is educational content material. I expect that differing peruses will in like way sell my house fast Florida encounter how I feel in the wake of examining your essay. In your blog, everything is good. You may remark on the request arrangement of the blog.

Reply
samAug. 9, 2019, 11:35 a.m.

The web site is lovingly serviced and saved as much as date. So it should be, thanks for sharing this with us. pengeluaran sgp

Reply
muneerAug. 14, 2019, 7:22 p.m.

Tot in de 20e eeuw was Harenkarspel ook een plaatsnaam. Rond 1295 werd er een terp opgeworpen ten oosten van Tuitjenhorn. Het land waarop de terp stond was in handen van de graven van Holland, Tuitjenhorn online services maar geschonken aan de abdij van Egmond.

Reply
samAug. 15, 2019, 10:27 a.m.

You have made some decent points there. I looked on the internet for more information about the issue and found most people will go along with your views on this web site. электро отопление для частного дома

Reply
samAug. 29, 2019, 10:40 a.m.

Your post has those facts which are not accessible from anywhere else. It’s my humble request to u please keep writing such remarkable articles Papas Games

Reply
digitincAug. 30, 2019, 12:44 a.m.

This is really very nice post you shared, I always prefer to read https://incentz.com/ the quality and glad I found this thing in your post. Thank you for posting such a great article.

Reply
digitincAug. 31, 2019, 8:24 a.m.

Nice blog and absolutely outstanding. You have a real ability for custom figure skating gifts writing unique content. It was really good to work. I really like your thoughts. Thanks for the great info for the idea.

Reply
mtomSept. 3, 2019, 3:31 p.m.

This is a really good read for me. Must agree that you are one of the coolest blogger I ever saw. Thanks for posting this useful information. This was just what I was on looking for. I’ll come back to this blog for sure! Barber Birmingham

Reply
MikeSept. 5, 2019, 7:56 a.m.

I am happy to read the article about custom drupal element forms which i like reading.I have learned a lot from this post which will help me in making my coding skills better. rubber matting with flexible quality

Reply
DavidSept. 5, 2019, 8:31 a.m.

Some element make API in drupal so powerful. I read this article and there are very important points in this post that is really useful in our life.Thanks and keep it up. london brick

Reply
wooden flooring costSept. 8, 2019, 9:47 a.m.

This article gives the light in which we can observe the reality. I am surely wooden flooring cost coming again for more content of yours. There is a sure way to create individual essays. am appreciating it very much! Looking forward to another great article.

Reply
samSept. 13, 2019, 11:12 a.m.

I was satisfied to discover this site.I needed to thank you for this incredible read!! I unquestionably getting a charge out of each and every piece of it and I have you bookmarked to look at new stuff you post. dj song download

Reply
mtomSept. 14, 2019, 11:41 a.m.

Fine website, in which did you come up with the info in this piece? I¡¯m pleased I uncovered it though, ill be checking back quickly to find out what other content articles you might have. 메이저사이트


It’s not that I want to copy your web page, but I really like the style and design. Could you let me know which design are you using? Or was it especially designed? Wet Shave

Reply
samSept. 16, 2019, 5:55 a.m.

The web site is lovingly serviced and saved as much as date. So it should be, thanks for sharing this with us. http://chan.jaka-moda.pl

Reply
samSept. 16, 2019, 11:35 a.m.

Amazing things you've for the most part conferred to us. Essentially proceed with composed work this kind of posts.The time which was wasted in going for instructive cost now it tends to be used for studies.Thanks hp plotter repair service

Reply
jeniffer leioSept. 17, 2019, 9:14 a.m.

Actually I read it yesterday but I had some thoughts about it and today I wanted to read it again because it is very well written mcafee.com/activate | canon printer support | sony printer support | samsung printer support | brother printer support | dell printer support

Reply
EVASept. 17, 2019, 11:41 a.m.

I am extremely impressed with your writing skills and also with the layout on your blog.lexmark printer support

Reply
digitincSept. 18, 2019, 5:36 a.m.

Your articles are inventive. I am looking forward to blackest black shirt reading the plethora of articles that you have linked here. Thank you for posting such a great article. Thanks for sharing this via your weblog.

Reply
EVASept. 18, 2019, 10:16 a.m.

Very thankful for such an amazing post.Hope for more similar posts in future also.Please keep sharing. canon printer support

Reply
samSept. 18, 2019, 7:21 p.m.

This is my first time visit to your blog and I am exceptionally intrigued by the articles that you serve. Give enough information to me. Much obliged to you for sharing valuable and remember, continue sharing helpful data: seo

Reply
samSept. 19, 2019, 8:07 a.m.

I am undeniably benefiting as much as possible from your site. You obviously have some remarkable information and unfathomable stories. jovell condo floor plan

Reply
EVASept. 19, 2019, 9:29 a.m.

Thank you to post such amazing and interesting blogs we really love to read it and hope for more.kodak printer support

Reply
EVASept. 20, 2019, 9:21 a.m.

I am very thankful to you for such an amazing post. Please post more like this as we really love to read it.epson printer support

Reply
samSept. 21, 2019, 11:09 a.m.

You completed certain reliable points there. I did a search on the subject and found nearly all persons will agree with your blog. shabunkins

Reply
samSept. 22, 2019, 6:05 p.m.

Gee!! This blog is truly cool, I'm fortunate to the point that I have come to here and got this great data. off page seo

Reply
samSept. 23, 2019, 6:35 a.m.

It was thinking about whether I could utilize this review on my other site, I will connect it back to your site though.Great Thanks. 온라인카지노주소추천

Reply
Eva wingetSept. 23, 2019, 10:14 a.m.

I'm really glad to find this amazing site.I need to thank you for this wonderful post.please keep sharing. accounting software support

Reply
Carol SpencerSept. 23, 2019, 12:19 p.m.

Hello there. It looks like a perfect mla format paper. Do you have some special skills? For me, it's a tough task to write a quality paper. I need to spend a lot of time for making a perfect assignment.

Reply
digitincSept. 24, 2019, 6:04 a.m.

This is a really very nice post you shared. It really makes Asian wedding cinematography Birmingham happy and I am satisfied with the arrangement of your post. Thank you for posting such a great article.

Reply
mtomSept. 26, 2019, 2:09 p.m.

gain expertise, would you mind updating your weblog with a great deal more details? It’s very beneficial for me. 먹튀검증

Reply
samSept. 24, 2019, 1:54 p.m.

Particular interviews furnish firsthand message on mart size, industry trends, ontogeny trends, capitalist landscape and outlook, etc. blog commenting

Reply
samSept. 26, 2019, 10:34 a.m.

I have added and shared your site to my social media accounts to send people back to your site because I am sure they will find it extremely helpful too. voyance medium

Reply
samSept. 26, 2019, 6:09 p.m.

People appreciate shopping for astounding, engaging, captivating and every once in a while alluring fragrances for them selves and relating to other people. This can be executed helpfully alongside modestly in an on-line aroma shop. high quality

Reply
digitincOct. 1, 2019, 6:11 a.m.

Thanks for sharing very useful information. Also, we are the manufacturer, Supplier, and trader of high-performance ‘die casting lubricant manufacturers’. Meiyahg Metal Casting mold release agent

Reply
Arlo PlastererOct. 3, 2019, 12:41 p.m.

Greetings once again it was a truly terrific adventure for me personally when I visited your blog. I just wanted to congratulate you on the exceptional quality of your work and also to wish you all the best with everything as you proceed as time goes on. It certainly was a pleasurable adventure to surf your website and I'll definitely be stopping by once again to see how you're getting on. Thanks a bunch and if luck is on my side I will doubtless see you here in the very near future - Arlo Plasterer

Reply
amazon prime dealsOct. 7, 2019, 5:26 a.m.

This article is an appealing wealth of useful informative that is amazon prime deals interesting and well-written. I just want to give an enormous thumbs up for the great info you have here on this post. Thank you for sharing.

Reply
samOct. 7, 2019, 12:58 p.m.

I used it for a month and saw a perceptible differentiation in myself. By and by I don't shy of going out with my friends, etc. 파워볼실시간

Reply
digitincOct. 12, 2019, 2:49 p.m.

I was surfing the Internet for information six sigma austin came across your blog. I am happy to find this post very useful for me, as it contains a lot of information. This is great content for your readers.

Reply
IDN PokerOct. 11, 2019, 4:02 p.m.

Kronospoker Situs Judi Online, IDN Poker, IDN Poker Mobile, Agen Poker Terpercaya Indonesia untuk permainan Poker Online, Domino Qiu Qiu, Ceme Keliling, Capsa Susun dan Super10

Reply
AlbaOct. 12, 2019, 10:43 p.m.

I really thank you for the valuable info on this great subject and look forward to more great posts.

mcafee.com/activate

Reply
samOct. 16, 2019, 7:51 a.m.

Extraordinary review, I am a major devotee to remarking on websites to illuminate the blog authors realize that they've added something advantageous to the internet!.. windshield replacement cost

Reply
corporate counselOct. 19, 2019, 5:26 a.m.

This is a wonderful content and Given so much info in it, These type of corporate counsel articles keeps the user's interest in the content. It is such a help for me you have made some good information. Thanks for sharing.

Reply

Post New Comment