views:

1568

answers:

1

I'm on a different path on the same site, and I need to allow the user to change the contents of a field on a node s/he wrote in a different location. I have the nodeid and the field name, and ids, etc np.

I don't believe this is too difficult, but a tutorial or an explanation would be wonderful.

Thanks.

Edit: Thank you anschauung for asking, so to clarify:

It is a CCK textarea. As for why, well there's a central node type, with many linked node reference nodes. From the edit page of any node which references the central node, it needs to be able to edit and save a field of the central node. So that's my usecase.

Thanks again.

Thanks you so much googletorp, I really really appreciate your help.

Here's what I have so far:

For step one:

function update_main_field_menu() {

  $items = array();

  $items['update_main_field/%'] = array(
    'title' => 'Update Main Field',
    'page callback' => 'post_to_main_node',
    'page arguments' => 1,
    'type' => MENU_CALLBACK
  );

  return $items;
}

Step two:

function post_to_main_node(){
    // Sorry, I'm totally lost. What do I put here?
}

Also you mentioned this:

Either in hook_form_alter, hook_nodeapi or some other hook that is invoked when the node form is generated. You should investigate which is best in your situation.

How do I generate the node form?

Step three:

function modulename_form_mainct???_node_form_alter (&$form, &$form_state) {

    // I'm not sure about which form I'm doing node form alter on. If I do it to the mainct, wouldn't that alter the regular edit page the user is viewing? I only want to load the js for the ajax submission. Is there a update_main_field node form?


    drupal_add_js(drupal_get_path('module', 'modulename') ."/updateField.js");
}

Also what is in between the function in step 2 and getting the node form in step 3?

Step 4: I think I understand mostly, though because of other things I can't test it yet. :)

I really want to learn how to do this in drupal, but it would be swell if you could increase the dumminess level of your language a bit. :D Thank you so much once again.


Edit again:

I actually tried putting access arguments yesterday, but for some reason it did not work. :( But now it does! Yay you have magic.

Now, when I trigger the post like this:

Drupal.behaviors.ajax_update_field = function (context) {
    $("#button").click(function(){
     var url = $("#edit-field-reference-0-nid-nid").val().replace(/.*?\[nid:(\d+)?]/ig, "$1");
     url =  "/update_main_field/"+url;

         // The data is just some silly test thing
     $.post(url, {data: $("#edit-field-reference-0-nid-nid-wrapper label").text()}, function(value) {

      // Here you can write your js to handle a response to the user,
      // or if something went wrong an error message.
      // value = response data from drupal

      alert(value);

     });
    });
}

I see a post to the url with the correct data. Which is good. But no response. The alert is empty.

Also a new blank... something has been created. There's nothing in it, but I can see it in views when filtered for nodes. It has no title, any fields, etc. Just a post date.

The node that I want to be updated isn't updated.

So that leads me to think that the step two is probably somewhat incorrect. I have a few questions about it.

function post_to_main_node(){

    // Is this sufficient to load the node? nid doesn't have to be set as an arg for the function?
    $node = node_load($_POST['nid']);

    // Is the field set like this? 'field_library' is the 'machine name' of the field. This is what's needed right?
    $node->field_library = $_POST['data'];
    node_save($node);
}

Thank you so much once again.

+3  A: 

This can be done quite easily, but there are a few steps to it.

Updated the code to show how I would do this. This code can almost be copied into your drupal project, but I haven't battle tested it, so there might be a typo here or a bug there.

  1. Setup a url you can post to using hook_menu(). You need to use the CALLBACK type. What you need to remember is to add some sort of access control to your menu item. If you don't no one can visit it, even user 1 since no access control is being made. In this case you should use the access arguments, and put the name of the perm that the user needs to have. You can use one that already exist in a different module, or you can create your own using hook_perm. You will need to make sure your users have the correct perm for them to be able to use this. This is done normally through the Drupal AI.

    function modulename_menu() {
        $items = array();
        $items['update_main_field'] = array(
            'page callback' => 'call_back',
            'type' => MENU_CALLBACK,
            'access arguments' => array('name of perm'),
        );
        return $items;
    
  2. Create a callback function that you specified, this is the function that will be run when some one visits the url.
    A simplyfied version looks like this. You would need to validate the data and do stuff like that before saving the node. You might also want to do a permission check.

    function call_back() {
        $result = array();
        // Here we check the date get the node, update the cck field and save it.
        $node = isset($_POST['nid']) ? node_load($_POST['nid']) : FALSE;
        // $node will be false if nid wasn't set or nid was invalid.
        if (!$node || !isset($_POST['text']); {
            $result['status'] = 'error';
            $result['message'] = t('error message');
        }
        // Check if the loaded node have the correct type so it will have the field we want.
        else if ($node->type != 'node_type') {
            $result['status'] = 'error';
            $result['message'] = t('error message');
        }
        else {
            $node->field = $_POST['text'];
            node_save($node);
            $result['status'] = 'success';
            $result['message'] = t('success message');
        }
        return drupal_json($result);            
    }
    
  3. Add the js file, this can be done with drupal_add_js(), you might want to look into drupal_get_path() to create the correct path for your js file. There are some different ways you can add the js file. Either in hook_form_alter, hook_nodeapi or some other hook that is invoked when the node form is generated. You should investigate which is best in your situation. If you go with hook_form_alter it would look something like this:

    modulename_form_alter(&$form, &$form_state, $form_id){
        // Add js to the desired node form.
        if ($form_id == 'content_type_name_node_form') {
            drupal_add_js(drupal_get_path('module', 'modulename') . '/script.js');
        }
    }
    
  4. Do your javascript stuff using jQuery this could look something like this, if you fx had a button and a textfield:

    $("#button_id#").click(function(){
        var nid = $("#edit-field-reference-0-nid-nid").val().replace(/.*?\[nid:(\d+)?]/ig, "$1");
        var text = $("#edit-field-reference-0-nid-nid-wrapper label").text();
        $.post("/update_main_field", {"nid": nid, "text", text}, function(data) {
            // This is basically how jQuery converts response data to json
            var json = eval("(" + data + ")");
            if (json['status'] == "error") {
                // Handle error cases.
            }
            else if (json['status'] == "success") {
                 // Handle the success case.
            }
        });
    });
    
  5. In your callback function you handle the data which will be in $_POST, and you should end your function by return json data, that your js can act upon to let the user know what happened. drupal_json can be used for this.
googletorp
Thank you so much. I replied in the question.
Mark
Thanks for the updated instructions! I created a module and tried it with some sample data. I see a post in firebug, but with 403 forbidden. I also get the access denied when I try to manually navigate to url. (all with user1). Do you know what could be wrong? Thanks.
Mark
Thank you so much once again. I updated my question with another edit. Thank you so much for your help.
Mark
Thank you, but I really am so confused. Why do I need to check the date? How do I get the node? Unlike the hook_perm page, or similar, the node_load api page has no examples. I also see no results when searching for $_post. http://api.drupal.org/api/search/6/%24_post . Is there a link that explains what that means and what the correct syntax is?
Mark
$_POST is a php super global, so you wont find it in the drupal api documentation, here's the link for it http://php.net/manual/en/reserved.variables.post.php . The first few lines explain very well how to use node_load:Load a node object from the database.Parameters$param Either the nid of the node or an array of conditions to match against in the database query.You need to check your data, to make sure that things doesn't go wrong, if you don't get the data you anticipated.
googletorp
Thank you, got it working after some trial and error.
Mark