# Contact Age Filter

This example demonstrates how to create a custom age range filter for a contacts app using the new `filterMicroappView` async API.

## Scenario

You have a contacts table with `name` and `age` fields, and you want to create a custom search panel that allows filtering contacts by age range.

## Implementation

```html
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        .filter-container {
            display: flex;
            gap: 10px;
            align-items: center;
            padding: 20px;
            font-family: Arial, sans-serif;
        }
        .filter-input {
            padding: 8px;
            border: 1px solid #ccc;
            border-radius: 4px;
            width: 80px;
        }
        .filter-button {
            padding: 8px 16px;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        .filter-button:hover {
            background: #0056b3;
        }
        .clear-button {
            padding: 8px 16px;
            background: #6c757d;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            margin-left: 5px;
        }
        .clear-button:hover {
            background: #545b62;
        }
    </style>
</head>
<body>
    <div class="filter-container">
        <label>Age from:</label>
        <input type="number" id="minAge" class="filter-input" value="20" min="0" max="120">
        <label>to:</label>
        <input type="number" id="maxAge" class="filter-input" value="30" min="0" max="120">
        <button onclick="applyFilter()" class="filter-button">Filter</button>
        <button onclick="clearFilter()" class="clear-button">Clear</button>
    </div>

    <script>
        let buzzyFrameAPI;
        let contactsTableID;

        (async function initializeAPI() {
            try {
                buzzyFrameAPI = new BuzzyFrameAPI();
                const { resourceJSON } = await buzzyFrameAPI.initialise();
                
                contactsTableID = resourceJSON.children?.find(
                    child => child.title === 'Contacts'
                )?._id;
                
                if (!contactsTableID) {
                    console.error('Contacts table not found in resourceJSON');
                }
            } catch (error) {
                console.error('Failed to initialize BuzzyFrameAPI:', error);
            }
        })();

        async function applyFilter() {
            if (!buzzyFrameAPI || !contactsTableID) {
                console.error('API not initialized or contacts table not found');
                return;
            }

            const minAge = parseInt(document.getElementById('minAge').value);
            const maxAge = parseInt(document.getElementById('maxAge').value);

            if (isNaN(minAge) || isNaN(maxAge)) {
                alert('Please enter valid age values');
                return;
            }

            if (minAge > maxAge) {
                alert('Minimum age cannot be greater than maximum age');
                return;
            }

            try {
                await buzzyFrameAPI.filterMicroappView({
                    microAppID: contactsTableID,
                    viewFilters: [
                        { age: { $gte: minAge } },
                        { age: { $lte: maxAge } }
                    ],
                    viewFilterIsMongoQuery: true,
                    filterContext: 'contact-age-filter'
                });
                console.log(`Applied age filter: ${minAge} to ${maxAge}`);
            } catch (error) {
                console.error('Failed to apply filter:', error);
            }
        }

        async function clearFilter() {
            if (!buzzyFrameAPI || !contactsTableID) {
                console.error('API not initialized or contacts table not found');
                return;
            }

            try {
                await buzzyFrameAPI.filterMicroappView({
                    microAppID: contactsTableID,
                    viewFilters: [],
                    viewFilterIsMongoQuery: true,
                    filterContext: 'contact-age-filter'
                });
                console.log('Cleared age filter');
            } catch (error) {
                console.error('Failed to clear filter:', error);
            }
        }
    </script>
</body>
</html>
```

## Key Points

### Modern Async API Approach

* Uses the new `filterMicroappView` async API instead of deprecated `filterview` postMessage
* Initializes BuzzyFrameAPI at the top level before React components
* Uses proper error handling with try/catch blocks

### MongoDB Query Syntax

* Uses `$gte` (greater than or equal) and `$lte` (less than or equal) operators
* Supports complex filtering with multiple conditions
* Set `viewFilterIsMongoQuery: true` to enable MongoDB operators

### User Experience Features

* Input validation to ensure valid age ranges
* Clear filter functionality to remove all filters
* Responsive design with hover effects
* Error handling with console logging

### Filter Context

* Uses `filterContext: 'contact-age-filter'` to identify this specific filter
* Allows multiple filters to coexist without conflicts
* Helps with debugging and filter management

## Migration from Deprecated filterview

If you're migrating from the old `filterview` postMessage approach:

**Old approach (deprecated):**

```javascript
window.parent.postMessage({
    from: 'buzzy-iframe',
    action: 'filterview',
    body: filterParams,
    frameToken: frameToken
}, '*');
```

**New approach (recommended):**

```javascript
await buzzyFrameAPI.filterMicroappView({
    microAppID: contactsTableID,
    viewFilters: filterParams.viewFilters,
    viewFilterIsMongoQuery: true,
    filterContext: 'your-filter-context'
});
```

## Testing the Example

1. Create a contacts app with `name` (text) and `age` (number) fields
2. Add some sample contacts with different ages
3. Add this code widget to a screen that displays the contacts table
4. Test filtering by different age ranges
5. Verify that the "Clear" button removes all filters


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.buzzy.buzz/the-building-blocks/code-widget-custom-code/examples/contact-age-filter.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
