1

I am having the following problem: the method binding for the tag <f:passThroughAttributes> used to populate the component with passthrough attributes is not called for AJAX Request.

<f:ajax execute="@this otherComponent"
        listener="#{myController.doSomething}"
        render="otherComponent">
   <h:inputText id="myComponent" value="#{myModel.value1}">
      <f:passThroughAttributes value="#{myController.getAttributesFor("myComponent")}" />
   </h:inputText>
</f:ajax>

<h:inputText id="otherComponent" value="#{myModel.value2}"></h:inputText>

Why isn't it called?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Willie C.
  • 13
  • 4
  • @BalusC: Sorry for the confusion. Next time i will try to make it better. the original code is to long to put it here;) The idea behind what i am trying to do is the same as what i am showing here. i removed the ":" because it was my mistake. Thanks for that. I also updated the code. Sorry for the confusion During the initial page load or other postbacks the getter methods of the are called. – Willie C. Dec 12 '13 at 13:20

1 Answers1

2

You never told <f:ajax> to render the current input component as well. Add @this to the render attribute.

<f:ajax ... render="@this otherComponent">

This must call the getter method and produce the desired HTML output. However, this will cause a new problem: passthrough attributes are ignored by Mojarra's ajax update script, see also line 1419 and forth of jsf.js of Mojarra 2.2.4 when project stage is set to Development (didn't check MyFaces on this one):

1419                } else if (d.nodeName.toLowerCase() === 'input') {
1420                    // special case handling for 'input' elements
1421                    // in order to not lose focus when updating,
1422                    // input elements need to be added in place.
1423                    parserElement = document.createElement('div');
1424                    parserElement.innerHTML = html;
1425                    newElement = parserElement.firstChild;
1426
1427                    cloneAttributes(d, newElement);
1428                    deleteNode(parserElement);
1429                }

So in order to keep input's focus (e.g. when triggered during keydown), it's not replacing the entire input element with the ajax-rendered one, but only cloning its attributes. However, the cloneAttributes() function only clones predefined HTML attributes such as id, class, etc, not custom ones and for sure not passthrough ones. To work around this, wrap the input element in a span and ajax-udpate it instead:

<h:panelGroup id="foo">
    <h:inputText id="myComponent" value="#{myModel.value1}">
        <f:passThroughAttributes value="#{myController.getAttributesFor("myComponent")}" />
        <f:ajax execute="@this otherComponent" 
                listener="#{myController.doSomething}" 
                render="foo otherComponent" />
   </h:inputText>
</h:panelGroup>
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks @BalusC. Solves that problem but there remains one question. ```f:passThroughAttributes``` as TagHandler is executed in ```RESTORE_VIEW-Phase``` while the Ajax-Listener is executed in ```INVOKE_APPLICATION-Phase```. So it seems that it’s not possible to get dynamic passThroughAttributes dependent on some Ajax-executed-businesslogic. Any ideas? Shall I open another question? – lefloh Dec 12 '13 at 14:55
  • The tag is indeed resolved during view build time, but the attribute values are resovled during view render time, so I don't understand what problem you're currently facing. Did you really apply the answer as to actually updating the component with the new attributes manipulated by ajax action? – BalusC Dec 12 '13 at 15:20
  • If I use the example above and ```myController.doSomething``` sets ```myModel.value1``` to the current time and ```myController.getAttributesFor``` adds this value as passThroughAttribute the value and the passThroughAttribute differ. The passThroughAttribute holds the value from one call before because this value was set in ```RESTORE_VIEW-Phase```. – lefloh Dec 12 '13 at 15:43
  • As said, it works for me. Attribute values are evaluated during view render time. Did you really update the input component's parent or at least `@form` as indicated in bottom of the answer? – BalusC Dec 12 '13 at 15:52
  • I did and changed to execute ```@form``` but same problem. I also changed to Mojarra 2.2.4 (was working with 2.2.2 before) but still same problem. I committed a [simple example on github](https://github.com/lefloh/jsf-dynamic-passthrough) if you want to take a look. – lefloh Dec 12 '13 at 17:07