[CLOSED] Trying to activate child event before the parents' event using (beforeselect)

  1. #1

    [CLOSED] Trying to activate child event before the parents' event using (beforeselect)

    Trying to activate child event before the parents' event using [beforeselect]

    Any equivalent to "beforeselect" and "beforedeselect" listener functionality?
    It seems to be missing and I am in need of this particular functionality.
    I have a populated list and the itemTpl containing textboxes.. I need to be able to click and edit the textboxes populated in the lsit without actually selecting (or deselecting) and highlighting the row, hence the reason why I require this functionality.

    Any help (or hint) would be much appreciated.

    Here is an example:
        <script runat="server">
        public object[] People
        {
            get
            {
                var rv = new List<object>();
    
                for (var x = 1; x < 50; x++)
                {
                    rv.Add(new
                    {
                        Name = "King Kung" + x
                    });
                }
    
                return rv.ToArray();
            }
        }
    </script>
    <ext:Container runat="server">
        <Items>
            <ext:List runat="server" AllowDeselect="true" EmptyText="Nothing to display" Mode="Multi" TriggerEvent="true"  >
                <ItemTpl runat="server">
                    <Html>
                        <div><input id="test" type="number" onclick="getTest(this)" value="8" /> {Name}</div>
                    </Html>
                </ItemTpl>
                <Listeners>
                   <Select Fn="selected" />
                    <Deselect Fn="deSelected" />
                </Listeners>
                 <Store>
                    <ext:Store runat="server" DataSource="<%# this.People %>">
                        <Model>
                            <ext:Model runat="server">
                                <Fields>
                                    <ext:ModelField Name="Name" />
                                </Fields>
                            </ext:Model>
                        </Model>
                    </ext:Store>
                </Store>
            </ext:List>
            
        </Items>
        </ext:Container>
    As you can see I have an itemTpl html code that includes a textbox with onclick event.
    Currently whenever I click on the row , it gets selected as normal.. But I want to stop the select/deselect event when the textbox is clicked/focused. I mean of course i can nullify the click even by setting triggerEvent to false..But then I won't be able to select/deselect.
    Last edited by fabricio.murta; Nov 30, 2017 at 11:25 PM.
  2. #2
    Hello @ojunior!

    Thanks for your question! But I'm quite lost on the question itself. Think you can come up with a simplified code sample to reproduce it so that we can try to help you out with that?..

    The forums guidelines might just help on that:
    - Tips for creating simplified code samples
    - More Information Required
    - Forum Guidelines

    Thanks for understanding!

    p.s.: confirming whether you are actually on Ext.NET Mobile also helps -- but by the code sample we can also infer that
    Fabrício Murta
    Developer & Support Expert
  3. #3
    I've included a code snippet.
  4. #4
    Hello @ojuniour!

    The way you are doing it looks really a pure-javascript issue, and this goes beyond Ext.NET support.

    But well, you want the item template script, I see two ways for you to do this:

    1. assign an unique ID to the text boxes then iterate thru them binding the event (or event stopper) to the HTML components.
    2. add a <script> block in the template body itself, with javascript code bind the event (or event stopper) to the individual HTML components.

    This can get more complex and beyond Ext.NET support. Ext.NET text fields do support handling their select and click/focus events, but event listener handling to Ext.NET components will be different (they use the 'listeners' and 'direct events' concepts) than simple/pure HTML elements.

    So for (1), you can do something like:

    <div><input id="test_{Id}" type="number" onclick="getTest(this)" value="8" /> {Name}</div>
    where Id would be another field in the store populating the list, besides Name. If you can guarantee Name will be unique in the list and contain only valid characters, you can just use id="test_{Name}", for instance.

    Then you can have javascript iterating thru the test_<whatever> components and bind the javascript events to prevent selection/deselection. And probably reiterate thru the list items to bind the events to them every time the list changes.

    As for (2), it would be just a <script /> block within the very template, with javascript code to bind the events to the immediate <input /> element. The problem here is that adding/removing elements to the list on the go won't run any script, as javascript is only run from pages' first load and, adding script tags don't get executed when programatically created.

    I hope this helps you clear up with the trouble you're facing!
    Fabrício Murta
    Developer & Support Expert
  5. #5
    Thanks for the Help.
    I did try solution #1 already (before posting) but the problem is the ext.NET select/deselect event still fires foremost first (when clicked) before my javascript code could be reached. It just always fires first no matter what I do.

    Solution #2 is not viable due to the drawback.
  6. #6
    Oh, I think I got your issue now. Providing a test case that actually could run would really help us understand your needs.

    By reading your last post, you suggest the Ext.NET select event is being triggered first, before the inner input field's onClick.

    I couldn't get this here. I have elaborated on your code snippet (please use this as a base for our next issues, having a runnable code sample does help a real deal) so I could see what is effectively being fired first:

    <%@ Page Language="C#" %>
    
    <!DOCTYPE html>
    
    <script runat="server">
        protected void btn1_DirectTap(object sender, DirectEventArgs e)
        {
        }
    
        public List<object> People = new List<object>()
        {
            new { Name = "Person 1" },
            new { Name = "Person 2" },
            new { Name = "Person 3" },
            new { Name = "Person 4" },
            new { Name = "Person 5" }
        };
    </script>
    <html>
    <head runat="server">
        <title></title>
        <script type="text/javascript">
            var evTriggerCount = 0;
            var selected = function () {
                console.log("[" + evTriggerCount++ + "] Ext.NET select trigger.");
            };
    
            var deSelected = function () {
                console.log("[" + evTriggerCount++ + "] Ext.NET deselect trigger.");
            };
    
            var innerClick = function (what) {
                console.log("[" + evTriggerCount++ + "] Inner element click happened.");
            }
        </script>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <ext:ResourceManager runat="server" SourceFormatting="false" />
            <ext:Container runat="server" FullScreen="true">
                <Items>
                    <ext:List runat="server" AllowDeselect="true" EmptyText="Nothing to display" Mode="Multi">
                        <ItemTpl runat="server">
                            <Html>
                                <div><input id="test" type="number" onclick="innerClick(this)" value="8" /> {Name}</div>
                            </Html>
                        </ItemTpl>
                        <Listeners>
                            <Select Fn="selected" />
                            <Deselect Fn="deSelected" />
                        </Listeners>
                         <Store>
                            <ext:Store runat="server" DataSource="<%# this.People %>">
                                <Model>
                                    <ext:Model runat="server">
                                        <Fields>
                                            <ext:ModelField Name="Name" />
                                        </Fields>
                                    </ext:Model>
                                </Model>
                            </ext:Store>
                        </Store>
                    </ext:List>
                </Items>
            </ext:Container>
        </div>
        </form>
    </body>
    </html>
    With this, if I click the entries in the sequence: 1st, 2nd, 3rd then 2nd again, I get this console output:

    [0] Inner element click happened.
    [1] Ext.NET select trigger.
    [2] Inner element click happened.
    [3] Ext.NET select trigger.
    [4] Inner element click happened.
    [5] Ext.NET select trigger.
    [6] Inner element click happened.
    [7] Ext.NET deselect trigger.
    So this suggests the event is propagating the expected way, from inside out. So all you need to do (that you probably already tried) is to stop the event propagation.

    But again, you'll notice that stopping the click propagation will do no good in your example. Why? Because Ext.NET Mobile is touch/tap driven. And they are separate events. And still, that's not all to it.

    If you add a breakpoint (using your browser debugging tools) to the select methods (either select or deselect), then click/tap within the input field of your list, you'll notice in the call stack a touchEnd method call which suggests the event that originated the selection. This means, holding off click events or even plain tap events will do no good. You have to hold the propagation on the touchend javascript event.

    So then you can make a more generic innerClick function from the above example into this:

    var innerEvent = function (what, ev) {
        console.log("[" + evTriggerCount++ + "] Inner element " + ev.type + " happened.");
        ev.stopPropagation();
    };
    Then change your input field to

    [code]
    <div><input id="test" type="number" ontouchend="innerEvent(this, event)" onclick="innerEvent(this, event)" value="8" /> {Name}</div>
    [code]

    You'll notice from this point on, the select/deselect events won't trigger. But still, an undesired visual effect will take place to the rows as they are clicked. If you click then outside the rows' input field you can select and deselect the row and the color effect goes away.

    This is because of a visual feedback that happens as soon as the item touch starts, a color effect is added on touch start then removed on touch end -- as we blocked touch end, the effect is never removed. So all we should do is inhibit touchstart event from making it outside the input field, and have a result where the "outside world" completely ignores interaction with the inner input fields.

    So then just change the input code to this:
    [code]
    <div><input id="test" type="number" ontouchend="innerEvent(this, event)" onclick="innerEvent(this, event)" value="8" /> {Name}</div>
    [code]

    And have the list ignore interaction (at least click/touchend/touchstart) from the inner input field. So, there's no telling how many different events may be triggered with the interaction with your input field. Identifying them and properly circumventing whenever they do undesired side effects are up to you, as this is pretty much hacking into Ext.NET event handling logic.

    Long story short, you want to event.stopPropagation() on touchstart and touchend events, not click.

    I hope this helps!
    Fabrício Murta
    Developer & Support Expert
  7. #7
    Apologies for the missing informations.
    Replacing onclick with just ontouchstart solves the problem beautifully.
    Fantastic!

    One curious question:
    Is the event similar to (or utilized in) 'beforeSelect/beforeDeselect'?
  8. #8
    Hello, glad it helped! Thanks for the feedback!

    About the before/ events, I didn't check actual code but usually they are associated to the same browser event, the before- takes place before layout and other interaction changes, and the other (usually just the event name without any 'after-' prefix) takes place after or immediately after these layout/interaction changes. In some circumstances they could be bound to different browser events to guarantee they are run before layout changes, although I don't have a practical example to point on top of my head.
    Fabrício Murta
    Developer & Support Expert
  9. #9
    Alright.
    Can this thread be marked as 'Resolved'?
  10. #10
    Yes, we will mark it as resolved! Thanks!
    Fabrício Murta
    Developer & Support Expert

Similar Threads

  1. Replies: 1
    Last Post: Nov 29, 2017, 4:08 PM
  2. Replies: 1
    Last Post: Jan 16, 2015, 6:41 AM
  3. [CLOSED] Combo BeforeSelect Event
    By softmachine2011 in forum 2.x Legacy Premium Help
    Replies: 2
    Last Post: Sep 07, 2012, 8:12 AM
  4. [CLOSED] Tab activate event
    By LeeTheGreek in forum 1.x Legacy Premium Help
    Replies: 4
    Last Post: Aug 01, 2010, 1:21 PM
  5. Tabpanel / Tab activate event
    By locoperoguapo in forum 1.x Help
    Replies: 1
    Last Post: Feb 17, 2009, 1:09 PM

Posting Permissions