Improving linksubmit in form loop?

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Improving linksubmit in form loop?

Chris Poulsen
Hi,

I've been working on a dynamic ajax form in 5.4; that allows users to
configure a list of things. The idea is that add / edit / delete operations
carry all data with them (form submits). The list is rendered as a list of
form-fields per row using a t:loop.

There have been some challenges, but I've managed to solve most of them
using the built in stuff (Somewhat creative use of t:trigger /
t:submitnotifier for managing the dynamic list of objects during
render/submit).

However I've not been successful adding a delete link (t:submitlink) to
each row. I want to indicate the particular row using the t:context
parameter, but that seems to be resolved in the "processSubmission" call.
And that is too late as both the current row / loop index are null
(obviously as they are a render thing).

I've hit many similar questions in google and most have been answered with
"set t:defer=false", but that does not make a difference in this case as
the context depends on the loop state during rendering.

So I decided to try an fix the problem with the context being resolved "too
late" and I would like some feedback on whether the suggested approach is
viable/correct or why not!

My attempted fix is a copy of the linksubmit that serializes the passed
context into its ProcessSubmission ComponentAction. I serialize/deserialize
the context using ContextPathEncoder (like the link components) - as I
figured that links are basically doing the same (serializing the event
context into a string and deserializing it back later on).

With this new linksubmit it seems like defer is not really needed anymore,
it does not matter if my links are deferred or not as the processSubmission
already has the correct state.

If my approach is sane, it could maybe be useful for someone else. If not
I'd be interested in fixing it - If possible.

The relevant parts of my linksubmit2 class are pasted below, the rest is a
copy of the standard linksubmit.

--
Chris


... Begin of paste
    @Inject
    private ContextPathEncoder contextPathEncoder;

    private static class ProcessSubmission implements
ComponentAction<LinkSubmit2>
    {
        private final String clientId;
        private final String encodedEventContext;

        public ProcessSubmission(String clientId, String
encodedEventContext )
        {
            this.clientId = clientId;
            this.encodedEventContext = encodedEventContext;
        }

        public void execute(LinkSubmit2 component)
        {
            component.processSubmission(clientId, encodedEventContext );
        }
    }

    private void processSubmission(String clientId, String
encodedEventContext )
    {
        this.clientId = clientId;
        final Object[] context = contextPathEncoder.decodePath(
encodedEventContext ).toStrings();

        String raw = request.getParameter( Form.SUBMITTING_ELEMENT_ID);

        if ( InternalUtils.isNonBlank( raw) && new JSONArray(
raw).getString( 0).equals( clientId))
        {
            Runnable notification = new Runnable()
            {
                public void run()
                {
                    resources.triggerEvent(event, context, eventCallback);
                }
            };

            if (defer)
                formSupport.defer(notification);
            else
                heartbeat.defer(notification);
        }
    }

    void beginRender(MarkupWriter writer)
    {
        if (!disabled)
        {
            clientId = javascriptSupport.allocateClientId(resources);
            String encodedContext = contextPathEncoder.encodeIntoPath(
context );
            formSupport.store(this, new ProcessSubmission(clientId,
encodedContext ));

            writer.element("a",

                           "href", "#",

                           "data-submit-mode", mode.name().toLowerCase(),

                           "id", clientId);

... End of paste