Forum Archive

Tableview updating data while using a filter

ramvee

Hi Friends,
I am trying to use a filter which must update the data source continuously in my tableview.
I figured it out for ui.LitsDataSource but i have wasted a couple of days trying to do the same with
MyTableViewDataSource method.
This filter was shown by a kind friend @Phuket2 about 2 years ago.
It was must a very simple mistake i am making, tried using reload() method too.
Here is my program, forgive the sloppiness..
Thank you.

# filtering data with two items per record
# example with tableview cells with subtitles
# And TableView Delegate method

import ui

items = [
    ['Pretty Woman', 'Julia Roberts'],  
    ['Seven Year Itch', 'Marilyn Monroe'],['Casablanca' , 'Ingrid Bergman'],
    ['Roman Holiday','Audrey Hepburn'],
    ['Sound Of Music','Julie Andrews'], 
    ['Love Story','Ali McGraw'],
    ['You Got Mail','Meg Ryan'],
    ['Clueless','Alicia Silverstone'],
    ['Great Gatsby','Mia Farrow'],
    ['Mask','Cameron Diaz']     
    ]

w,h = ui.get_screen_size()
h=h-64
gap = 5
fontsize = 15 if w<750 else int((w / 75) + 16)

def reload_data():
    tbl.data_source.reload()

class MyTableViewDataSource (object):
    def tableview_cell_for_row(self, tableview, section, row):
        row_title, row_description = items[row]
        # 'subtitle'-style cells come with a built-in secondary label
        cell = ui.TableViewCell('subtitle')
        cell.text_label.text = row_title
        cell.text_label.text_color = 'blue'
        cell.detail_text_label.text = row_description
        cell.detail_text_label.text_color = 'slateblue' #'#555'
        return cell

    def tableview_number_of_rows(self, tableview, section):
        return len(items)

class MyTableViewDelegate (object):
        def tableview_did_select(self, tableview, section, row):
            print(f'{items[row][0]}, {items[row][1]}')

class MyTextFieldDelegate (object):
    items = items or []
    def textfield_did_change(self, textfield):
        self.filter_data(textfield.text)

    def filter_data(self, filter_text=''):
        ft = filter_text.lower()
        if not len(ft):
            tbl.data_source.items = self.items
        else:
            for s in self.items:
                if ft in (s[0].lower()) or ft in (s[1].lower()):
                    tbl.data_source.items = s
                    ## Need this to be updated
                    ## in the tableview 

view = ui.View(name='Filter Items', frame =(0,0,w,h), bg_color='slateblue')

tf = ui.TextField(frame=(gap,gap,w-gap*2,32), flex='w', placeholder='Search', clear_button_mode='always')
tf.delegate = MyTextFieldDelegate()
view.add_subview(tf)

tbl = ui.TableView(frame=(gap,42,w-gap*2,h-42), corner_radius=3, flex='wh')
tbl.row_height=fontsize*2.5
tbl.name = 'Item Table'
tbl.separator_color = 'grey'
tbl.data_source = MyTableViewDataSource()
tbl.delegate = MyTableViewDelegate()
view.add_subview(tbl)

view.present('sheet', title_bar_color= 'slateblue')
cvp

@ramvee try this

import ui

items = [
    ['Pretty Woman', 'Julia Roberts'],  
    ['Seven Year Itch', 'Marilyn Monroe'],['Casablanca' , 'Ingrid Bergman'],
    ['Roman Holiday','Audrey Hepburn'],
    ['Sound Of Music','Julie Andrews'], 
    ['Love Story','Ali McGraw'],
    ['You Got Mail','Meg Ryan'],
    ['Clueless','Alicia Silverstone'],
    ['Great Gatsby','Mia Farrow'],
    ['Mask','Cameron Diaz']     
    ]

w,h = ui.get_screen_size()
h=h-64
gap = 5
fontsize = 15 if w<750 else int((w / 75) + 16)

#def reload_data():                             # deleted
#    tbl.data_source.reload()           # deleted

class MyTableViewDataSource (object):
    def tableview_cell_for_row(self, tableview, section, row):
        row_title, row_description = items[row]
        # 'subtitle'-style cells come with a built-in secondary label
        cell = ui.TableViewCell('subtitle')
        cell.text_label.text = row_title
        cell.text_label.text_color = 'blue'
        cell.detail_text_label.text = row_description
        cell.detail_text_label.text_color = 'slateblue' #'#555'
        return cell

    def tableview_number_of_rows(self, tableview, section):
        return len(tableview.data_source.items)                         # changed

class MyTableViewDelegate (object):
        def tableview_did_select(self, tableview, section, row):
            print(f'{items[row][0]}, {items[row][1]}')

class MyTextFieldDelegate (object):
    items = items or []
    def textfield_did_change(self, textfield):
        self.filter_data(textfield.text)

    def filter_data(self, filter_text=''):
        ft = filter_text.lower()
        if not len(ft):
            tbl.data_source.items = self.items
        else:
            new_items = []                                      # added
            for s in self.items:
                if ft in (s[0].lower()) or ft in (s[1].lower()):
                    new_items.append(s)                 # changed
            tbl.data_source.items = new_items       # changed
            tbl.reload()                                                # changed

view = ui.View(name='Filter Items', frame =(0,0,w,h), bg_color='slateblue')

tf = ui.TextField(frame=(gap,gap,w-gap*2,32), flex='w', placeholder='Search', clear_button_mode='always')
tf.delegate = MyTextFieldDelegate()
view.add_subview(tf)

tbl = ui.TableView(frame=(gap,42,w-gap*2,h-42), corner_radius=3, flex='wh')
tbl.row_height=fontsize*2.5
tbl.name = 'Item Table'
tbl.separator_color = 'grey'
tbl.data_source = MyTableViewDataSource()
tbl.data_source.items = items                               # added
tbl.delegate = MyTableViewDelegate()
view.add_subview(tbl)

view.present('sheet', title_bar_color= 'slateblue') 
ramvee

Thank You Very Much For The Prompt Reply @cvp !
I can figure it out now. :)

ramvee

Thank you @cvp for all your help and @Phuket2 for filtering code.
I have put up the fully working version below.
I use this to order a lot of books for our bookstore.
I have the csv data file with a few thousand records of book title and book author.

import ui

items = [
    ['Pretty Woman', 'Julia Roberts'],  
    ['Seven Year Itch', 'Marilyn Monroe'],
    ['Casablanca' , 'Ingrid Bergman'],
    ['Roman Holiday','Audrey Hepburn'],
    ['African Queen','Katherine Hepburn'],
    ['Out Of Africa','Meryl Streep'],
    ['Cleopatra','Elizabeth Taylor'],
    ['Titanic','Kate Winslet'],
    ['Apartment','Shirley MacLaine'],
    ['West Side Story','Natalie Wood'],
    ['Rear Window','Grace Kelly'],
    ['Pillow Talk','Doris Day'],
    ['Sound Of Music','Julie Andrews'], 
    ['Love Story','Ali McGraw'],
    ['You Got Mail','Meg Ryan'],
    ['Clueless','Alicia Silverstone'],
    ['Great Gatsby','Mia Farrow'],
    ['Mask','Cameron Diaz'],
    ['Kill Bill', 'Uma Thurman'],
    ]

w,h = ui.get_screen_size()
h=h-64
gap = 5
fontsize = 15 if w<750 else int((w / 75) + 16)

class MyTableViewDataSource (object):
    def tableview_cell_for_row(self, tableview, section, row):
        row_title, row_description = tableview.data_source.items[row]
        # 'subtitle'-style cells come with a built-in secondary label
        cell = ui.TableViewCell('subtitle')
        cell.text_label.text = row_title
        cell.text_label.text_color = 'blue'
        cell.detail_text_label.text = row_description
        cell.detail_text_label.text_color = 'slateblue'
        return cell

    def tableview_number_of_rows(self, tableview, section):
        return len(tableview.data_source.items)

class MyTableViewDelegate (object):
        def tableview_did_select(self, tableview, section, row):
            main, desc = tableview.data_source.items[row]
            print(f'{main}, {desc}')

class MyTextFieldDelegate (object):
    items = items or []
    def textfield_did_change(self, textfield):
        self.filter_data(textfield.text)

    def filter_data(self, filter_text=''):
        ft = filter_text.lower()
        if not len(ft):
            tbl.data_source.items = self.items
            tbl.reload()
        else:
            tbl.data_source.items = [s for s in self.items if (ft in s[0].lower()) or (ft in s[1].lower())]
            tbl.reload()

view = ui.View(name='Filter Items', frame =(0,0,w,h), bg_color='slateblue')

tf = ui.TextField(frame=(gap,gap,w-gap*2,32), flex='w', placeholder='Search', clear_button_mode='always')
tf.delegate = MyTextFieldDelegate()
view.add_subview(tf)

tbl = ui.TableView(frame=(gap,42,w-gap*2,h-42), corner_radius=3, flex='wh')
tbl.row_height=fontsize*2.5
tbl.name = 'Item Table'
tbl.separator_color = 'grey'
tbl.data_source = MyTableViewDataSource()
tbl.data_source.items = items
tbl.delegate = MyTableViewDelegate()
view.add_subview(tbl)

view.present('sheet', title_bar_color= 'slateblue')