#Introduction

In this lab you'll show Yelp information in a `Neo.table.Container`.

#Steps

??Import Table

Edit `yelp/view/businesses/Tabs.mjs` and import _src/table/Container.mjs_ &mdash;
make sure you use the correct relative path.

??Make the second tab the table

Configure the second tab to use imported `Neo.table.Container`. Configure the 
button text to be _Table_, and use `iconCls:'fas fa-table-list'` (or any other icon
you think looks good).

If you save and refresh you should see the warning _Attempting to create a table.Container without defined columns..._. We'll fix that in the next step.

??Start to configure the columns

We want to show the business name, street address, telephone, star rating, and review count.

Configure a `columns:[]` with five columns whose `text` is: _Name_, _Address_, _Telephone_, _Rating_, and _Reviews_.

??Plan how to show the data

Here's what a business looks like in the data feed: 

    {
        "name": "Pizza Brutta",
        "review_count": 422,
        "rating": 4.5,
        "coordinates": {
            "latitude": 43.06512,
            "longitude": -89.41629
        },
        "location": {
            "display_address": [
                "1805 Monroe St",
                "Madison, WI 53711"
            ]
        },
        "display_phone": "(608) 257-2120"
    }

There are already two fields in each record. The fields match what the Google Maps component expects
for its store: 

- _title_, which is mapped to _name_
- _position_, which uses a `calculate` to create a object with _lat_ and _lng_

We need four more values: _address_, _telephone_, _rating_, and _reviews_.

Some of those map directly to their value in the feed, some need a `mapping` config. 

Showing `address` is a little trickier. We have two choices: we can configure a `calculate` 
in the store model's `fields[]`, or code a table column renderer to get the value. 

We'll try both techniques.

??Add field definitions

Edit the main view model `businesses` store config and add four fields:

 - _reviews_, which is mapped to _review_count_
 - _rating_
 - _phone_, which is mapped to _display_phone_
 - _address_, which is mapped to _location.display_address_

We aren't using these in the table yet, but you can still verify that the store
is getting the right data by getting a reference to the map and looking at its
store items.

    Neo.findFirst({ntype:'googlemaps'}).markerStore.items

Each item should six properties that look like this:

    {
        "title": "Pizza Brutta",
        "position": {
            "lat": 43.06512,
            "lng": -89.41629
        },
        "reviews": 422,
        "rating": 4.5,
        "telephone": "(608) 257-2120",
        "address": [
            "1805 Monroe St",
            "Madison, WI 53711"
        ],
        "id": -1
    }

??Continue to configure the table

Edit `yelp/view/businesses/Tabs.mjs` and add a `dataField` config for each column using 
the corresponding value specified in store's `fields:[]`.

Also specify `align:'right'` for ratings and review count.

Of course, we won't see anything until you bind the table to the store. Configure the
binding. This is the same as the map binding, except table has a _store_ rather than
a _markerStore_.

Save and refresh, and you should see data in the store. If you change the city or category
the table should update accordingly.

??Use renderers

We need some renderers.

Configure a renderer for the address.

    renderer: data => data.value.join(', ')

Configure a renderer for the review count.

    renderer: data => new Intl.NumberFormat().format(data.value)

Configure a renderer for the rating.

    renderer: data => new Intl.NumberFormat('en-US', {minimumFractionDigits: 1})
        .format(data.value)

Save, refresh and try it out. You should see the renderers being used.

??Use a calculated value in the store

Go back to the main view model and modify the _address_ field config to use a `calculate`.

    calculate: (record, field, data) => data.location.display_address.join(', ')

Then remove the `renderer` from the table.

??Calculating store values versus table renderers

Is it better to calculate values as you populate a store, or is it better 
to user renderer functions to do the calculation?

Ideally, you want good data-view separation. In other words, you create your data stuctures 
to use sensible primitive values, then have the UI display those in ways that makes sense 
for a given part of the UI. That may mean formatting values. 

Dates are a good example: stores will hold dates, but you don't want to store date strings, 
because the view will decide how to format a date for that particular part of the UI. The
same holds for numbers, which may or may not be displayed with thousands separators, etc. 

In the case of the address &mdash; which Yelp provides as an array of address parts &mdash; it's a
toss-up. An array of address parts seems more primitive and flexible, so maybe it's 
preferable to have the view provide the renderer. But maybe not!


