Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-20286] Support getElementById method to lookup views by ID

GitHub Issuen/a
TypeNew Feature
PriorityHigh
StatusClosed
ResolutionFixed
Resolution Date2017-01-05T01:26:47.000+0000
Affected Version/sn/a
Fix Version/sRelease 6.1.0
ComponentsAndroid, iOS, Windows
Labelsandroid, ios, windows
ReporterJeff Haynie
AssigneeHans Knöchel
Created2016-01-28T17:48:57.000+0000
Updated2018-06-04T08:36:12.000+0000

Description

To facilitate a common web pattern (such as JQuery $ or DOM selector getElementById), we should support a simple selector like syntax or at a minimum getElementById-like API. My suggestion would be something like Ti.UI.getViewById which would return the view object or null if not found.

Comments

  1. Jeff Haynie 2016-01-28

    http://stackoverflow.com/questions/35068169/select-dynamically-generated-element-by-id-in-titanium-appcelerator/35068348#35068348
  2. Hans Knöchel 2016-12-11

    [~cng] This is currently scheduled for 6.1.0. Thinking about the implementation, we could use the proposed Ti.UI.View.getViewById method and inherit it to the subclasses of it. We would set the id property of the proxy and loop through the view's children to determine the correct view. I don't see many problems there, and parity would be doable as well. /cc [~gmathews] iOS/Android PR: https://github.com/appcelerator/titanium_mobile/pull/8677 Test-Case:
       var win = Ti.UI.createWindow({
           backgroundColor: '#fff'
       });
       
       var container = Ti.UI.createView({
           width: 300,
           height: 300,
           backgroundColor: 'red'
       });
       
       var btn = Ti.UI.createButton({
           title: 'Get view by ID',
           id: 'myButton'
       });
        
       btn.addEventListener('click', function() {
           var myButton = win.getViewById('myButton');
           
           // If no button is found, it will return null
           if (myButton) {
               myButton.setTitle('Worked!');
           }
       });
        
       container.add(btn);
       win.add(container);
       win.open();
       
    This change is perfect for unit-tests as well. Will do those this week.
  3. Chris Barber 2016-12-12

    jQuery's $() is effectively document.querySelectorAll(), which is actually pretty involved. Simply being able to find a UI element by ID is going to be MUCH easier and it's a good start. If we plan to support something like document.querySelectorAll(), which I support, then it really needs to work with CSS selector syntax. However, it makes the most sense to support this in the context of Alloy where there are "tags". If this ticket is to only support getting an element by ID, then we should update this ticket's title. [~hansknoechel] Note that getElementById() will return an array of elements if there are more than one that matches the specified ID. Not saying we need to do the same, but it's a great idea.
  4. Hans Knöchel 2016-12-12

    [~eharris] Yes, definitely! [~cbarber] Thanks for the feedback! I guess we can expose all selectors then. And I'll change the existing implementation to return an array for multiple results.
  5. Chris Barber 2016-12-12

    [~hansknoechel] "Expose all selectors"? Not sure I follow.
  6. Hans Knöchel 2016-12-12

    I meant the querySelectorAll method. So we would support something like view.querySelectorAll('#myButton, .myLabel')? In Alloy, I think that classes are assigned using the className property, so we could search that one as well. Then we would need an algorithm to process the arguments and implement it on each platform. If so, we should move the whole thing to 6.2.0 and think about a proper architecture first.
  7. Chris Barber 2016-12-12

    That's what I'm getting at. Adding a "get by id" is easy and we should do today, but supporting selectors is not easy and probably only makes sense in the context of Alloy. So, probably best to rename this ticket to "get element by id" and create a new ticket to support selectors.
  8. Hans Knöchel 2016-12-12

    Agree, thx Chris! Created TIMOB-24213 as a follow-up.
  9. Kota Iguchi 2016-12-21

    PR for Windows: https://github.com/appcelerator/titanium_mobile_windows/pull/911
  10. Samir Mohammed 2017-01-13

    Verified improvement with the test case provided above, no error is shown when getElementById is used. *iOS and Android environment*
        Appcelerator Command-Line Interface, version 6.1.0
        Android 7.1 (Google Nexus 6P)
        iOS 10.1.1 (iPhone 7)
        Operating System Name: Mac OS X El Capitan
        Operating System Version: 10.11.6
        Node.js Version: 4.6.0
        npm: 4.2.8
        Titanium SDK Version: 6.1.0.v20170112013001
        Xcode: 8.2
        Appcelerator Studio: 4.8.1.201612050850
        
    *Windows Environment*
        Nokia Lumia 640 LTE (RM-1073)
        Version 1607 (OS build: 10.14393.576)
        Operating System
        Name                        = Microsoft Windows 10 Pro
        Version                     = 10.0.14393
        Architecture                = 64bit
        

    CPUs = 4

    Memory = 17034395648 Node.js Node.js Version = 4.4.4 npm Version = 2.11.3 Titanium SDK SDK Version = 6.1.0.v20170112013001
  11. Andrea Vitale 2018-06-04

    I'm using the latest 7.2.0 build and getViewById works well on iOS, not on Android.
        <Alloy>
        	<TableViewRow>
        		<View class="w-fill h-size vertical">
        			<Label id="Primary" />
        			<Label id="Secondary" />
        		</View>
        		<View id="Accessory">
        			<View id="Child" />
        			<ActivityIndicator id="Loader" />
        		</View>
        	</TableViewRow>
        </Alloy>
        
    If I try to get the ActivityIndicator reference using const loader = event.row.getViewById('Loader'); inside the TableView click event, on iOS it correctly gives me the ActivityIndicator instance, on Android gives a null value.

JSON Source