#Introduction

In this lab you'll update the property as the text fields change.

#Steps

??Update `city` as the user types.

We want changes in the text field to be reflected in the filter's `city` property.

To do that, listen to the field's `change` event, and in the handler get a 
reference to the parent container, and assign the value to it's `city` property.

    listeners: {
        change: (data) => data.component.up('yelp-filter').city = data.value
    }

Test this by entering text in the city field &mdash; you should see a the console
log being run on each keypress.

??Do the same for `category`

Add a similer `listeners` config to the category field. 

Test this by entering text in the category field &mdash; you should see a the console
log being run on each keypress.

??Plan a way to buffer or _debounce_ the updates

Conceptually, `Yelp.view.business.Filter` has `city` and `category` properties.

"Madison" is a city, but "M" and "Ma" and "Mad" are not cities, so the
_city_ property shouldn't reflect those intermediate values. Therefore,
we need code to defer updating the property until the user appears to have 
finished typing. 

There are various ways to create a _buffer_ or _debouce_ fuctions, and
we found one via an internet search. We need a place to hold our implementation.

??Add a utility class with a `debounce` function

Use a terminal to navigate to the Neo workspace, and run `npm run create-class`.
    
- Name the class "Yelp.util.Function"
- Extend `Neo.core.Base
- Make it a singleton

Edit the new file and add the debounce routine highlighted below.

<pre style="border: thin solid gray; padding: 8px; color: lightgray;font-size:14pt;">
import Base from '../../../node_modules/neo.mjs/src/core/Base.mjs';

class Function extends Base {
    static config = {
        className: 'Yelp.util.Function',
        singleton: true
    }
    <span style="color:#b91010;">debounce(func, wait, immediate) {
        let timeout
        return function (...args) {
            clearTimeout(timeout)
            timeout = setTimeout(() => {
                timeout = null
                if (!immediate) func.apply(this, args)
            }, wait)
            if (immediate && !timeout) func.apply(this, [...args])
        }
    }</span>
}

Neo.setupClass(Function);

let instance = Neo.create(Function);

Neo.applyToGlobalNs(instance);

export default instance;
</pre>

??Buffer the updates

Edit `view/businesses/Filter.mjs` and add this import.

    import Function from '../../util/Function.mjs';

And add a method designed to do a buffered update to a property.

    doBufferedUpdate(property, value) {
        this._bufferedUpdate = this._bufferedUpdate || Function.debounce((property, value) => this[property] = value, 500);
        this._bufferedUpdate(property, value);
    }

??Use the new function when the city text field changes 

Modify the city's `change` listener to use the new function.

    listeners: {
        change: (data) => data.component.up('yelp-filter').doBufferedUpdate('city', data.value)
    }

Test the changes by running the app, and type a city name. After the 500ms delay 
you should see the city name logged. Note that running 
    
    Neo.findFirst({ntype:'yelp-filter'}).city = 'Madison'

logs the city name immediately. Changing the city to a new value updates
immediately. We only need to buffer changes when the user is typing.

??Have the category field do the same thing

Make a similar change to the category field config.

    listeners: {
        change: (data) => data.component.up('yelp-filter').doBufferedUpdate('category', data.value)
    }
