Flagging Form integration with node reference

483 views Asked by At

I'm currently doing recruitment system by using drupal 7..

In my system, the applicant need to fill up one time online resume if they want to apply the job.

I create a content type name "Applicant Profile" for online resume..

After that, i create the flag to let the applicant can select the job..the flag name is "Apply Now" which the flag type is "node"..

The flag link type i choose "Confirmation form" where applicant need to fill up the pitch for themselves to stand up with other applicant.

In that form got "Applicant name" with node reference field type and "Pitch" with long text field type.

My question is how to make it the applicant name appear automatic in the applicant name field? because my problem is, the applicant need to select their own name.

p/s : the node reference (applicant name field) will point to the applicant profile (online resume)..

Thank You.

1

There are 1 answers

1
Pebbl On

First I'll outline how I understand your set-up, along with my assumptions, because without seeing any code it is tricky to follow exactly:

  1. I assume you are using an up-to-date Drupal 7, with the latest node reference and flag module. If you aren't up-to-date you should be, if you are using anything less than D7 this most likely won't work. With D8 you may be ok, but I haven't had a chance to test it.

  2. You have a content type Applicant Profile which the user can create, my assumption is that they can create multiple profiles?

  3. You have your Apply Now flag which is set to appear on your advertised jobs, assuming that Job is a content type.

  4. When a user clicks Apply Now on a Job they are taken to the flag confirmation form, which asks them to select their Applicant Profile and fill out some text.

If all of the above are true then there isn't a way to accurately select the correct application profile automatically, because they can create more than one (and may wish to select one on an arbitrary choice), however you can make some educated guesses.


field settings

I'm not sure how you are displaying the Applicant Profiles in the select box, you may just be relying on the content type checkbox in the field settings of your Applicant Name node reference... if so, you should switch to using a view to select the items to display. This way you have greater control on how the list is generated... which includes being able to control the order of display. You'll find the following section at the bottom of the field settings form for a node reference field. Before you can use it however you need to create a references view.

node reference view screenshot

You should define this view so that it works with your profile content type and orders by most recent content at the top. Once editing the view add a references display. Set this display to take a UID as a contextual argument, that gets its value from the logged in user if there is no argument passed. Then set your view up to display whatever text you want for each application profile and make sure you are filtering to only show those profiles owned by the UID.


bespoke code

It would be best for the next step if you were to create your own bespoke module that best describes (and keeps contained) the changes you are making. Usually developers either use the project name (for the core project module) or the name of the add-on you might be building. If you already have a bespoke module that may fit the bill you can merge the following code into that module. If the module already has a hook_form_alter implemented, just copy the if ( $form_id === 'flag_confirm' ) { ... } block into that hook. Remember you will have to replace HOOK_ with the name of your module. For example, my most recent module was called tate_microsites so the hook would be tate_microsites_form_alter.

NOTE: If you haven't created any bespoke modules before you can also copy this code into your site's theme template.php (making sure you replace HOOK_ with your theme name i.e. bartik_form_alter).

/**
 * Implements hook_form_alter().
 *
 *  Steps in, finds the flag confirmation form, and causes the 
 *  'Applicant Name' field to select its second most item.
 */
function HOOK_form_alter(&$form, &$form_state, $form_id) {
  if ( $form_id === 'flag_confirm' ) {
    /// make sure our form has the field we are looking for
    if ( !empty($form['field_applicant_name']) ) {
      $und = LANGUAGE_NONE;
      /// grab out the possible options, rendered by our view
      $options = &$form['field_applicant_name'][$und]['#options'];
      /// shift on to avoid the _none option
      next($options);
      /// Set the default value to the second item, using its key.
      $form['field_applicant_name'][$und]['#default_value'] = key($options);
    }
  }
}

Once this code is in your site remember to clear caches and then visit the form in question, you should see that the first real item in the list is selected. This makes the assumption that the user will want to select their most recently created profile, but seeing as the select box is still accessible they can choose another if they so wish.


troubleshooting

If you find the above doesn't work you will need to make certain that the $form_id and field name are correct, and that you have replaced HOOK_ with the correct name for where you are placing the code. If you are using a specific language you may need to alter the use of LANGUAGE_NONE to the language of your choice. If it still fails make sure that you have cleared caches and do not have any other caching systems that could be causing issues like varnish, memcache or APC.


workings

Just to explain how I arrived at this solution — as the pattern is generally the same for most simple Drupal modifications — first off you need to choose your hook. In this case, because we wish to modify the way a field is behaving, your first place to look is always either hook_form_alter or hook_field_preprocess. I went for the former this time because I knew I wanted the field items to be fully calculated, and by the time we are in form_alter this is the case. If you aren't aware of what Drupal hooks are available you can normally search Google with the keywords "drupal hook" and whatever else you are attempting, to uncover a lot of information. However, there is also this list, which is by no means exhaustive, especially when you take into account contrib hooks from installed modules.

Anyway, once with the correct hook, I generally do the following initially:

function HOOK_form_alter(&$form, &$form_state, $form_id) {
    watchdog(__FUNCTION__ . ':' . $form_id, '<xmp>' . print_r($form, TRUE) . '</xmp>');
}

NOTE: Obviously if you have any debug modules installed you can use their debug message handling instead, but this is generally a quick fallback.

With the above code live and caches cleared, you should perform the action that will trigger the debug message. In this instance we need to visit the form we are working on. After that our debug message should be available in watchdog (remember, this will only work if you have logging enabled).

With this output we should be able to find out two things, the form id we need to target — in this case it was flag_confirm — and the construction of the field, who's output should look like the following:

[field_applicant_name] => Array
    (
        [#type] => container
        [#attributes] => Array
            (
                [class] => Array
                    (
                        [0] => field-type-node-reference
                        [1] => field-name-field-applicant-name
                        [2] => field-widget-options-select
                    )
            )
        [#weight] => 1
        [#tree] => 1
        [#language] => und
        [und] => Array
            (
                [#entity] => stdClass Object
                    (
                        [flagging_id] => 
                        [flag_name] => apply_now
                        [fid] => 2
                        [entity_type] => comment
                        [entity_id] => undefined
                        [uid] => 
                        [sid] => 
                    )
                [#entity_type] => flagging
                [#bundle] => apply_now
                [#field_name] => field_applicant_name
                [#language] => und
                [#field_parents] => Array
                    (
                    )
                [#columns] => Array
                    (
                        [0] => nid
                    )
                [#title] => Applicant Name
                [#description] => 
                [#required] => 
                [#delta] => 0
                [#type] => select
                [#default_value] => Array
                    (
                    )
                [#multiple] => 
                [#options] => Array
                    (
                        [_none] => - None -
                        [297541] =>  Pebbl Profile
                        [297543] =>  Another profile
                    )
                [#value_key] => nid
                [#element_validate] => Array
                    (
                        [0] => options_field_widget_validate
                    )
                [#properties] => Array
                    (
                        [strip_tags] => 1
                        [optgroups] => 1
                        [empty_option] => option_none
                        [filter_xss] => 
                    )
                [#after_build] => Array
                    (
                        [0] => field_form_element_after_build
                    )
            )
        [#access] => 1
    )

From this output and cross referencing with Drupal Form API you should be able to see how the end result was calculated. The two key elements are #default_value and #options.

Update

Well, again, without seeing more of the views and other items you have in place; it is tricky to advise. However, as long as you have your field in the flag confirmation form, that is rendering the possible applications to select, you can still use the following form_alter to modify that field.

If your field currently lists every possible profile, then as long as you have some way of identifying which profile is owned by the currently signed in user, you can scan through the options and pick the one that is required (just like my code does above, albeit for the first item in the list).

/**
 * Implements hook_form_alter().
 *
 *  Steps in, finds the flag confirmation form, and causes the 
 *  'Applicant Name' field to select its second most item.
 */
function HOOK_form_alter(&$form, &$form_state, $form_id) {
  global $user; /// access to the $user object
  if ( $form_id === 'flag_confirm' ) {
    /// make sure our form has the field we are looking for
    if ( !empty($form['field_applicant_name']) ) {
      $und = LANGUAGE_NONE;
      /// grab out the possible options, rendered by our view
      $options = &$form['field_applicant_name'][$und]['#options'];
      /// start with nothing selected
      $selected = '';
      /// here you could implement your search code
      foreach ( $options as $application_nid => $option ) {
        if ( ... ) {
          $selected = $application_nid;
          /// update the select box to only have one option
          $form['field_applicant_name'][$und]['#options'] = array(
            "$selected" => $option
          );
          break;
        }
      }
      if ( $selected ) {
        /// Set the default value to the correct application
        $form['field_applicant_name'][$und]['#default_value'] = $selected;
        /// Because this field has been auto selected, and only has one option
        /// you might as well hide it from the user.
        $form['field_applicant_name']['#access'] = 0;
      }
    }
  }
}

Obviously in the above you would have to replace ... with your logic for selecting the correct application. But this all depends on exactly how you have this relationship set up in your system. You do have access to the $user object, but you may have to make some other kind of database look-up or load to get all the information you need to find the right application. It is fully possible to node_load each $application_nid and compare $user->uid against the $application->uid, however I wouldn't recommend this, especially if the list of applications could get large. Instead, if you need to load extra information for the comparison you should look to using EntityFieldQuery to locate the application itself and then compare that against the items in the options list.

The above is still not the most optimal way of doing things, as it would be far better to have either the options list being generated based on the current logged in user by default (meaning there will only ever be one item to select, which can be achieved using views and then have the selection automatic) or to rely on the flagging relationship and ignore having the application directly selected by the user. However, without at least seeing an example export & screenshot of your attempted view (one you mentioned in your comment about displaying both Application and Pitch) I can't really aid much further.