Jump to:

17452 Posts in 4473 Topics by 1971 members

Archive

SilverStripe Forums » Archive » Updating MemberTableField on save

Our old forums are still available as a read-only archive.

Moderators: martimiz, Sean, biapar, Willr, Ingo, simon_w

Page: 1 2
Go to End
Author Topic: 5074 Views
  • Nathan Cox
    Avatar
    Community Member
    99 Posts

    Updating MemberTableField on save Link to this post

    Hi,

    In a site I'm working on I have a page type that has_one member group. In the page's getCMSFields() I'm using a MemberTableField to let the user add members to that page's group.

    I want it to work like an ImageField, so when you create a new page it displays a message telling you to save before you can edit the group, which is replaced by the MemberTableField subform when you save a draft.

    The problem is I can't get it to load the form when the page is saved. I've tried using FormResponse::update_dom_id() in the page's onBeforeWrite() but I can't figure out how to get the actually HTML for the form...using $MemberTableField->renderWith('MemberTableField') causes errors, and anything else prints either "(none)" or "MemberTableField".
    The only way I can get it to display is by refreshing the page (so it's created by getCMSFields()), which is just an extra hassle for the user.

    Does this make sense? Has anybody else done something like this before that could help me out?

  • elijahlofgren
    Avatar
    Google Summer of Code Hacker
    222 Posts

    Re: Updating MemberTableField on save Link to this post

    Hi Nathan,

    > $MemberTableField->renderWith('MemberTableField') causes errors, and anything else prints either "(none)" or "MemberTableField".

    I ran into this problem when I was working on making the Recipients tab in a Newsletter Mailing List get reloaded after new Recipients were imported.

    I ended up using this in cms/code/NewsletterAdmin.php (comments added):

       /**
        * Reloads the list of recipients via ajax
        */
       function getrecipientslist() {
          if( $_REQUEST['ajax'] ) {
             $newsletterType = DataObject::get_by_id('NewsletterType', $this->urlParams['ID'] );
             $fields = new FieldSet($memberList = new MemberTableField($this, "Recipients", $newsletterType->Group() ));
             // These 3 lines seem to be required to prevent fatal errors
             $memberList->setController($this);
             $actions = new FieldSet(new FormAction('save','Save'));
             $form = new Form($this, "EditForm", $fields, $actions);
             return $memberList->FieldHolder();
             // Instead of the above line which calls
             // ComplexTableField->FieldHolder() in sapphire/forms/ComplexTableField.php,
             // you can use the 2 lines below to use a custom template for
             // the MemberTable Field
             // $memberList->sourceItems();
             // return $memberList->renderWith('MemberTableFieldtemptest');
          }
       }

    Then in cms/javascript/NewsletterAdmin_right.js I used this Javascript to get the "response.responseText" and use it to update the list:

    function reloadRecipientsList() {

       var id = $('Form_EditForm_ID').value;

        var request = new Ajax.Request(baseHref() + 'admin/newsletter/getrecipientslist/' + id + '?ajax=1', {
          onSuccess: function( response ) {
             $('Root_Recipients').innerHTML = response.responseText;
             Behaviour.apply( $('MemberList') );
          },
          onFailure: function(response) {
             statusMessage('Could not automatically refresh recipients list', 'bad');
          }
       });   
    }

    I hope this helps. Let me know if you run into any problems and I'll be glad to try and help.

    Have a great Sunday,

    Elijah Lofgren

  • Nathan Cox
    Avatar
    Community Member
    99 Posts

    Re: Updating MemberTableField on save Link to this post

    Thanks, you're a legend...problem is it's still not entirely working.

    I've got the form appearing now (thanks!), but it won't do anything. I fill in a user's details and click 'Add' and nothing happens. Firebug says no AJAX happened.
    I'm guessing the problem is that the javascript isn't getting applied...I don't really know Prototype of Behaviour at all, but I wonder if Behaviour.apply() doesn't work because the element didn't exist before - there was just a ReadonlyField telling you to save first.

    What javascript do I need to say "apply this JS object to this bit"? The code that I THINK does it normally (in MemberTableField.js) is

    MemberTableField.applyTo('#Form_EditForm div.MemberTableField');

    but if I use that, it just tells me MemberTableField is undefined...

  • elijahlofgren
    Avatar
    Google Summer of Code Hacker
    222 Posts

    Re: Updating MemberTableField on save Link to this post

    Hi Nathan,

    You've helped me discover a bug! ;)

    My reloadRecipientsList() function is broken.

    The add button does not work after it is called.

    I get "FATAL ERROR: Object::__call() Method 'addtogroup' not found in class 'Form'
    At line 159 in /var/www/silverstripe-gsoc/sapphire/core/Object.php"

    It seems that it's not working to apply behaviour to stuff put in inner HTML.

    I will work on fixing this after lunch and let you know of the outcome.

    Cheers,

    Elijah

  • elijahlofgren
    Avatar
    Google Summer of Code Hacker
    222 Posts

    Re: Updating MemberTableField on save Link to this post

    Ok, this is strange. It seems to work perfectly after making this change:

    Index: cms/javascript/NewsletterAdmin_right.js
    ===================================================================
    --- cms/javascript/NewsletterAdmin_right.js (revision 39154)
    +++ cms/javascript/NewsletterAdmin_right.js (working copy)
    @@ -482,7 +482,7 @@

    var request = new Ajax.Request(baseHref() + 'admin/newsletter/getrecipientslist/' + id + '?ajax=1', {
    onSuccess: function( response ) {
    - $('Root_Recipients').innerHTML = response.responseText;
    + $('Root_Recipients').outerHTML = response.responseText;
    Behaviour.apply( $('MemberList') );
    },
    onFailure: function(response) {

    Time for me to go read up on the differences between innerHTML and outerHTML. ;)

  • elijahlofgren
    Avatar
    Google Summer of Code Hacker
    222 Posts

    Re: Updating MemberTableField on save Link to this post

    As noted on What are innerText, outerText, innerHTML and outerHTML?
    and Andy in #silverstripe today:

    16:24 <@ajoneil> outerHTML replaces the whole content of that node, including its start and
    end tags
    16:24 <@ajoneil> innerHTML leaves the start and end tags alone

    I also found that The jsenv bookmarklet is an even greater Debugging Tool than I thought it was.

    I was able to use the Firebug console in the jsenv window to see the error as shown in the attached screenshot:

    I've currently looking at the diff of HTML generated by the "View Generated Source" option of the Firefox Web Developer extension to see if I can see what's happening with the HMTL, but I think the "this.parentNode has no properties
    http://localhost/silverstripe-gsoc/cms/javascript/MemberTableField.js
    Line 119" error will probably provide the clue for why it doesn't work with
    innerHTML.

    Cheers,

    Elijah

  • elijahlofgren
    Avatar
    Google Summer of Code Hacker
    222 Posts

    Re: Updating MemberTableField on save Link to this post

    Could it be that using innerHTML makes parentnode get lost which makes 'this.parentNode has no properties' error about this line: var data = this.parentNode.parentNode.getElementsByTagName('input');?

    Just as I was about to give up on trying find out why: Aha! I saw extra newlines in the diffs, but I didn't think they were important:
    1. Rewriting content with Javascript: "This works in Safari and Internet Explorer, but encounters a bug in Firefox. In particular, each time the content is replaced via innerHTML, an additional newline (vertical whitespace) is inserted into the document. ... With a shallow clone and the innerHTML technique, we avoid the newline bug in Firefox and Mozilla. Further, we can allow rich markup in our replacement fragments."
    2. Cleaning useless whitespace in Mozilla DOM: "Now, from my preliminary testing, this method doesn't remove visibly intruding textNodes like the functions in this post do, but any reference you make (firstChild, parentNode, etc) after enacting normalize() will grab the expected node, and not any intermediary textNode. "
    3. Bug: Mozilla reports existence of phantom text nodes in the DOM
    4. Whitespace in the DOM - MDC

    Time to try some stuff! ;)

  • elijahlofgren
    Avatar
    Google Summer of Code Hacker
    222 Posts

    Re: Updating MemberTableField on save Link to this post

    I give up. I'm going to test that outerHTML works in IE6, IE7, and Safari 3 and just use that if it does. ;)

    5074 Views
Page: 1 2
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.