Details

    • Type: Improvement Improvement
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 1.1.2-SNAPSHOT
    • Fix Version/s: None
    • Component/s: General
    • Labels:
      None

      Description

      Here is a patch with docs for the ifMessage component I donated.

      1. ifMessageDocs.patch
        4 kB
        Mike Youngstrom

        Activity

        Hide
        Mike Youngstrom added a comment -

        diff for docs.

        Show
        Mike Youngstrom added a comment - diff for docs.
        Hide
        Adam Winer added a comment -

        I think this functionality could more cleanly be provided with an object in the EL that could be used to set rendered:

        <h:outputText rendered="#

        {myFaces.messagePresent['someComponentId']}

        "/>

        There's not much gained by building an entire component for this.

        Show
        Adam Winer added a comment - I think this functionality could more cleanly be provided with an object in the EL that could be used to set rendered: <h:outputText rendered="# {myFaces.messagePresent['someComponentId']} "/> There's not much gained by building an entire component for this.
        Hide
        Mike Youngstrom added a comment -

        I agree. And perhaps it is lack of JSF knowledge on my part but the main struggle I had with such a solution is being able to obtain the full clientIds without a starting point in the component tree. So, I figured a component solved that problem by providing an initial location in the tree to begin looking for components that may have messages.

        Do you have a good idea of how the messagePresent function could easily find 'someComponentId' without having to provide the entire client-id? In addition be able to obtain the correct client-id inside of a datatable?

        Mike

        Show
        Mike Youngstrom added a comment - I agree. And perhaps it is lack of JSF knowledge on my part but the main struggle I had with such a solution is being able to obtain the full clientIds without a starting point in the component tree. So, I figured a component solved that problem by providing an initial location in the tree to begin looking for components that may have messages. Do you have a good idea of how the messagePresent function could easily find 'someComponentId' without having to provide the entire client-id? In addition be able to obtain the correct client-id inside of a datatable? Mike
        Hide
        Mike Kienenberger added a comment -

        I disagree, although not strongly. Considering that you'd have to implement an EL function with the "map-property-as-a-function" hack for non-facelets JSF, I think a component provides a much cleaner solution.

        It's also easier/safer to install a new component than it is to install a new resolver. With a resolver, you'll have to deal with interactions with other custom resolvers.

        Show
        Mike Kienenberger added a comment - I disagree, although not strongly. Considering that you'd have to implement an EL function with the "map-property-as-a-function" hack for non-facelets JSF, I think a component provides a much cleaner solution. It's also easier/safer to install a new component than it is to install a new resolver. With a resolver, you'll have to deal with interactions with other custom resolvers.
        Hide
        Adam Winer added a comment -

        Mike Y: that is a tough problem: you don't have the current UIComponent to find from - which is unfortunate. If the target UIComponent had a "binding" associated, then life would be simple:

        <h:inputText binding="#

        {bean.someComponent}

        "/>
        <h:outputText rendered="#

        {myFaces.messagePresent[bean.someComponent]}

        "/>

        Mike K.: it would be a very good thing for MyFaces to have a single VariableResolver that installs a custom "myFaces" object (and only that) - and with that done, no, there really wouldn't be much in the way of interactions with other resolvers to worry about, or any safety issues. Then, within that object, you could have any sort of map-property-as-function objects, etc., and add other things that really belong in the EL instead of as components (a list of SelectItems for countries comes to mind).

        Show
        Adam Winer added a comment - Mike Y: that is a tough problem: you don't have the current UIComponent to find from - which is unfortunate. If the target UIComponent had a "binding" associated, then life would be simple: <h:inputText binding="# {bean.someComponent} "/> <h:outputText rendered="# {myFaces.messagePresent[bean.someComponent]} "/> Mike K.: it would be a very good thing for MyFaces to have a single VariableResolver that installs a custom "myFaces" object (and only that) - and with that done, no, there really wouldn't be much in the way of interactions with other resolvers to worry about, or any safety issues. Then, within that object, you could have any sort of map-property-as-function objects, etc., and add other things that really belong in the EL instead of as components (a list of SelectItems for countries comes to mind).
        Hide
        Mike Youngstrom added a comment -

        >Mike Y: that is a tough problem: you don't have the current UIComponent to find from - which is unfortunate. If the target UIComponent had a "binding" associated, then life would be simple:
        >
        > <h:inputText binding="#

        {bean.someComponent}

        "/>
        > <h:outputText rendered="#

        {myFaces.messagePresent[bean.someComponent]}

        "/>

        That's exactly the only solution that I could come up with too. It gets really messy when you have large forms with many input components.

        There have been several cases where designers have layed out a form and specified how error messages are to displayed and it turns out that by adding the error message support html messes up the format of the form. So this was really built as a way to help remove excess error message markup for a component or small group of components.

        Anyway, I think it is a fine solution that has its place and, gets the job done, and doesn't muddle up backing beans with binding variables. So what do you think Adam? Is it an acceptable solution?

        Mike

        Show
        Mike Youngstrom added a comment - >Mike Y: that is a tough problem: you don't have the current UIComponent to find from - which is unfortunate. If the target UIComponent had a "binding" associated, then life would be simple: > > <h:inputText binding="# {bean.someComponent} "/> > <h:outputText rendered="# {myFaces.messagePresent[bean.someComponent]} "/> That's exactly the only solution that I could come up with too. It gets really messy when you have large forms with many input components. There have been several cases where designers have layed out a form and specified how error messages are to displayed and it turns out that by adding the error message support html messes up the format of the form. So this was really built as a way to help remove excess error message markup for a component or small group of components. Anyway, I think it is a fine solution that has its place and, gets the job done, and doesn't muddle up backing beans with binding variables. So what do you think Adam? Is it an acceptable solution? Mike
        Hide
        Martin Marinschek added a comment -

        For me, it is definitely acceptable.

        It's a small comp, that helps in a certain way and makes life much easier for people wanting to do stuff this way.

        If it helps Mike, who is a very active member of the community, and there is no easy workaround, why not take it in?

        regards,

        Martin

        Show
        Martin Marinschek added a comment - For me, it is definitely acceptable. It's a small comp, that helps in a certain way and makes life much easier for people wanting to do stuff this way. If it helps Mike, who is a very active member of the community, and there is no easy workaround, why not take it in? regards, Martin
        Hide
        Martin Marinschek added a comment -

        After some time has passed by, I'm thinking differently about this one as well.

        This is my current take at this problem:

        1) go with Adam's suggestion of using a custom VariableResolver which adds a new implicit object (let's call it myfacesContext), add an attribute storedComponentClientId to this implicit object.

        2) create a new component which does nothing but setting the parent-client-id into this myfacesContext, e.g.: <t:storeParentComponentClientId param="#

        {myfacesContext.storedComponentClientId}

        "/>
        where param is optional (by default, it's set to where the example points, you can change this to somewhere else if need be).

        3) now you can use this stored-client-id in your el-expressions, and do a lot more than what ifMessage would provide.

        regards,

        Martin

        Show
        Martin Marinschek added a comment - After some time has passed by, I'm thinking differently about this one as well. This is my current take at this problem: 1) go with Adam's suggestion of using a custom VariableResolver which adds a new implicit object (let's call it myfacesContext), add an attribute storedComponentClientId to this implicit object. 2) create a new component which does nothing but setting the parent-client-id into this myfacesContext, e.g.: <t:storeParentComponentClientId param="# {myfacesContext.storedComponentClientId} "/> where param is optional (by default, it's set to where the example points, you can change this to somewhere else if need be). 3) now you can use this stored-client-id in your el-expressions, and do a lot more than what ifMessage would provide. regards, Martin
        Hide
        Martin Marinschek added a comment -

        I forgot to add: if someone implements this suggestion, I'd happily commit it!

        regards,

        Martin

        Show
        Martin Marinschek added a comment - I forgot to add: if someone implements this suggestion, I'd happily commit it! regards, Martin
        Hide
        Mike Youngstrom added a comment -

        So just to make sure we're on the same page, from a use case standpoint this is how someone would use something like this to determine if messages should be displayed.

        <h:form id="someForm">
        <t:storeParentComponentClientId var="someFormId"/>
        <h:inputText id="name" required="true"/>
        <h:panelGroup rendered="#

        {myfacesContext.ifMessage[parentClientId+':name']}

        ">
        <!-- some markup to support the error message -->
        <h:message for="name"/>
        </h:panelGroup>
        </h:form>

        I was a little unclear in your comment above about how #

        {myfacesContext.storedComponentClientId}

        correlated with t:storeParentComponentClientId.

        I can see how a component like storeParentComponentClientId could be useful in doing something like this. Is something like this what you were referring to?

        Show
        Mike Youngstrom added a comment - So just to make sure we're on the same page, from a use case standpoint this is how someone would use something like this to determine if messages should be displayed. <h:form id="someForm"> <t:storeParentComponentClientId var="someFormId"/> <h:inputText id="name" required="true"/> <h:panelGroup rendered="# {myfacesContext.ifMessage[parentClientId+':name']} "> <!-- some markup to support the error message --> <h:message for="name"/> </h:panelGroup> </h:form> I was a little unclear in your comment above about how # {myfacesContext.storedComponentClientId} correlated with t:storeParentComponentClientId. I can see how a component like storeParentComponentClientId could be useful in doing something like this. Is something like this what you were referring to?
        Hide
        Martin Marinschek added a comment -

        Not quite - you wouldn't need to provide a var, cause the parentComponentClientId would always store the client-id of its immediate parent (optionally, one might supply a for-attribute for the then renamed component).

        So it would look like this:

        <h:form id="someForm">

        <t:storeParentComponentClientId/>

        <h:inputText id="name" required="true"/>
        <h:panelGroup rendered="#

        {myfacesContext.ifMessage['name']}

        ">
        <!-- some markup to support the error message -->
        <h:message for="name"/>
        </h:panelGroup>
        </h:form>

        and the internal implementation of ifMessage would look up the component by finding first the parent component (for which it has the client-id) and then finding the component with the id name on the parent.

        regards,

        Martin

        Show
        Martin Marinschek added a comment - Not quite - you wouldn't need to provide a var, cause the parentComponentClientId would always store the client-id of its immediate parent (optionally, one might supply a for-attribute for the then renamed component). So it would look like this: <h:form id="someForm"> <t:storeParentComponentClientId/> <h:inputText id="name" required="true"/> <h:panelGroup rendered="# {myfacesContext.ifMessage['name']} "> <!-- some markup to support the error message --> <h:message for="name"/> </h:panelGroup> </h:form> and the internal implementation of ifMessage would look up the component by finding first the parent component (for which it has the client-id) and then finding the component with the id name on the parent. regards, Martin
        Hide
        Mike Kienenberger added a comment -

        Seems like we should be discussing this on dev rather than in the issue tracker. Few people are going to be following the issue.

        In my opinion, I don't see why you wouldn't use

        <h:panelGroup rendered="#

        {myfacesContext.ifMessage['someForm:name']}

        ">

        That's far less limiting that having to set something with a taghandler.

        Show
        Mike Kienenberger added a comment - Seems like we should be discussing this on dev rather than in the issue tracker. Few people are going to be following the issue. In my opinion, I don't see why you wouldn't use <h:panelGroup rendered="# {myfacesContext.ifMessage['someForm:name']} "> That's far less limiting that having to set something with a taghandler.

          People

          • Assignee:
            Martin Marinschek
            Reporter:
            Mike Youngstrom
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:

              Development