Applying User Filters

To apply a user filter to the specified view at runtime. The method validates the value against the filter's data type, applies it, refreshes the view, and returns a Promise that resolves on success or rejects with a descriptive error.

Returns: a Promise.

  • Resolves once the filter is applied and the view has refreshed.
  • Rejects with an error object describing the validation failure. The message is available as err.errorDesc (falling back to err.message). See the User Filter Change Event & Error Handling page for the full list of error messages.

For more detailed information, check the following help documentation regarding the User filter configuration and User filter error handling.

Function Call

ObjName.applyUserFilter(columnLabel, values, dataType, exclude)

Parameters

Parameter NameDescription
columnLabel*

String

The column label / name of the user filter as configured in the view. 
Column names are matched case-insensitively and trimmed of surrounding whitespace, so 'sales', 'Sales', and ' Sales ' all resolve to the same filter.

values*

String / Number / Array / Object

The filter value(s) to apply. 
The accepted format depends on the filter's data type, check the Accepted Value Formats below.

Pass the keyword 'RESET' to clear the filter and show all data.

null, undefined, and '' (empty string) are treated as a no-op (no change).

dataType

String

Explicitly sets the filter data type, bypassing auto-detection.

Use this when the value could be ambiguous or when you want to force a specific interpretation. One of the 33 supported data types (e.g. NUMERIC_SINGLE_SELECT, CATEGORICAL_MULTI_SELECT, DATE_ACTUAL_YEARS, DATE_SEASONAL_QUARTERS, DATE_RANGE, DURATION, TIMELINE).

exclude

Boolean / String

When value is true, the filter is applied in NOT-IN (exclude) mode - the view shows everything except the given values. Defaults to false.

Not supported for single-select filters.

Accepted Value Formats

The values argument adapts to the filter's data type. All formats below can be combined with the exclude flag (except single-select).

Filter TypeAccepted valuesExample
Numeric – singleNumber or numeric stringapplyUserFilter('Sales', '100')
Numeric – multiCSV string or Array

applyUserFilter('Sales', '4,5,2')

applyUserFilter('Sales', [4, 5, 2])

Numeric – slider range'from:to' string or 
{ from, to } object

applyUserFilter('Sales', '100:500')

applyUserFilter('Sales', { from: 100, to: 500 })

Categorical (text) – singleStringapplyUserFilter('Region', 'East')
Categorical (text) – multiCSV string or Array (spaces around commas are trimmed)

applyUserFilter('Region', 'Delhi,Goa')

applyUserFilter('Region', ['Delhi', 'Goa'])

Date Range

{ from, to } object or 'from to to' string

Either bound may be omitted for an open-ended range

applyUserFilter('OrderDate', { from: '01 Jan 2025', to: '31 Mar 2025' })
Date RelativeRelative phrase

applyUserFilter('OrderDate', 'Last 6 Months')

'This Week' , 'Next 10 Days' , 'Previous Year' , 'All'

Date Actual – single

String

Year / Quarter-year / Month-year / Week-year / full date / datetime

Also accepts relative phrases

applyUserFilter('Year', '2024')  

applyUserFilter('Quarter', 'Q1 2025')

applyUserFilter('Date', 'Jan 05, 2025')

Date Actual – multi

Array or CSV

May mix absolute + relative values

applyUserFilter('Year', ['2023', '2024'])

applyUserFilter('Year', ['Last 6 Months', '2024'])

Date Seasonal

Single, CSV, or Array

Quarter (Q1Q4), Month (JanDec), Week (Week 1Week 53), Weekday (MonSun), Day of month (131), Hour (023)

applyUserFilter('Season', 'Q2')

applyUserFilter('Season', ['Q1', 'Q2'])

DurationFormatted string, raw seconds, or a range as { from, to } / 'from to to'

applyUserFilter('Duration', '0 days 00:17:05')

applyUserFilter('Duration', '1025')

TimelineRange in year / quarter / month / week / day / datetime form, a relative phrase, or { from, to }

applyUserFilter('Timeline', '2022 - 2024')

applyUserFilter('Timeline', 'Q1 2022 - Q2 2023')

applyUserFilter('Timeline', { from: '01 Jan 2022', to: '31 Dec 2024' })

Any type – reset'RESET'applyUserFilter('Region', 'RESET')

Notes

  • Exclude mode:applyUserFilter('Region', 'Delhi,Goa', 'CATEGORICAL_MULTI_SELECT', true) shows everything except Delhi and Goa.
  • No-op values:null, undefined, and '' leave the filter unchanged and do not raise an error.
  • Whitespace around values (e.g. ' 100 ') is trimmed before applying.
  • Sequential / concurrent calls are supported; each applied filter stacks on the view.

Sample Response

The live preview embeds the report with two user filters, each wired to a custom control on the page:

  • Region : single‑select. Applies one value, e.g. applyUserFilter('Region', 'East').
  • Date : multi‑select quarters. Applies an array, e.g. applyUserFilter('Date', ['Q1', 'Q3'], 'DATE_SEASONAL_QUARTERS').

This sample is built as a complete, end‑to‑end example and brings every customization together in one place:

It combines every customization in one example:

  • Config - default values are pre-applied at load and the filter tab is hidden (userfilterHolderState: 'hidden'), so the page controls drive all filtering.
  • Event - the USER_FILTER_CHANGE listener updates the "Last filter event" line on each apply.
  • Errors - invalid input rejects the Promise and is shown via .catch(); the Apply invalid value button demonstrates this.

For more details, please refer to User Filter Configurations and Validations

How this sample behaves – the custom controls call applyUserFilter to filter the embedded report:

ControlIt callsResult
RegionapplyUserFilter('Region', value)Works – Region is a user filter on the report.
Date (quarters)applyUserFilter('Date', [...])Fails – report has no user filter named "Date", so it returns No User Filter found with the name Date.
Apply invalid valueapplyUserFilter('Date', 'Q5')Same "not found" error – the label is checked before the value, so it never reaches the Q5 quarter check.

The live preview below demonstrates this in action.

ZAnalytics JS API - applyUserFilter (full example)

Region

Select
East
West
Central

Date (quarters)

Select
Q1
Q2
Q3
Q4

Last filter event:none yet
 
 

Sample Code:

Copied<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>ZAnalytics JS API - applyUserFilter (full example)</title>
    <link rel="icon" type="image/x-icon" href="https://analytics.zoho.com/favicon.ico">
    <script src="https://downloads.zohocdn.com/zanalyticslib/jsapi/v1.2.0/zanalytics.min.js"></script>
    <style>
        :root {
            --filter-bg: #ffffff;
            --filter-border: #d1d5db;
            --filter-border-focus: #2563eb;
            --filter-shadow: 0 1px 2px rgba(0,0,0,0.05);
            --filter-shadow-focus: 0 0 0 3px rgba(37, 99, 235, 0.15);
            --filter-radius: 8px;
            --filter-height: 40px;
            --filter-text: #1f2937;
            --filter-muted: #6b7280;
            --filter-hover: #f3f4f6;
            --filter-arrow: #6b7280;
            --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        }
        * { box-sizing: border-box; }
        body { margin: 0; font-family: var(--font-sans); font-size: 14px; color: var(--filter-text); }
        .filter-bar {
            background: var(--filter-bg); border: 1px solid var(--filter-border); border-radius: 12px;
            padding: 20px 24px; margin-bottom: 16px; box-shadow: 0 1px 3px rgba(0,0,0,0.06);
        }
        .filter-bar-inner { display: flex; flex-wrap: wrap; align-items: center; gap: 20px 28px; }
        .filter-group { display: flex; align-items: center; gap: 8px; }
        .filter-label { font-weight: 600; color: var(--filter-muted); white-space: nowrap; font-size: 13px; }

        /* Custom select (single + multi share the shell) */
        .custom-select-wrap { position: relative; width: 180px; min-height: var(--filter-height); }
        .custom-select-trigger {
            width: 100%; height: var(--filter-height); padding: 0 36px 0 14px; background: var(--filter-bg);
            border: 1px solid var(--filter-border); border-radius: var(--filter-radius); cursor: pointer;
            display: flex; align-items: center; font-size: 14px; color: var(--filter-text);
            box-shadow: var(--filter-shadow); transition: border-color 0.15s, box-shadow 0.15s;
            overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
        }
        .custom-select-trigger .text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .custom-select-trigger:hover { border-color: #9ca3af; background: var(--filter-hover); }
        .custom-select-trigger:focus { outline: none; border-color: var(--filter-border-focus); box-shadow: var(--filter-shadow-focus); }
        .custom-select-trigger .arrow {
            position: absolute; right: 12px; top: 50%; transform: translateY(-50%); width: 0; height: 0;
            border-left: 5px solid transparent; border-right: 5px solid transparent;
            border-top: 6px solid var(--filter-arrow); pointer-events: none; transition: transform 0.2s;
        }
        .custom-select-wrap.open .custom-select-trigger .arrow { transform: translateY(-50%) rotate(180deg); }
        .custom-select-dropdown {
            position: absolute; left: 0; right: 0; top: calc(100% + 4px); background: var(--filter-bg);
            border: 1px solid var(--filter-border); border-radius: var(--filter-radius);
            box-shadow: 0 4px 12px rgba(0,0,0,0.1); z-index: 100; max-height: 240px; overflow-y: auto; display: none;
        }
        .custom-select-wrap.open .custom-select-dropdown { display: block; }
        .custom-select-option { padding: 10px 14px; cursor: pointer; transition: background 0.1s; display: flex; align-items: center; gap: 8px; }
        .custom-select-option:hover { background: var(--filter-hover); }
        .custom-select-option.selected { background: #eff6ff; color: var(--filter-border-focus); font-weight: 500; }
        .custom-select-option input { pointer-events: none; }

        /* Demo button + status */
        .demo-btn {
            height: var(--filter-height); padding: 0 16px; border: 1px solid var(--filter-border);
            border-radius: var(--filter-radius); background: #fff7ed; color: #9a3412; font-weight: 600;
            cursor: pointer; font-size: 13px;
        }
        .demo-btn:hover { background: #ffedd5; }
        .status-bar {
            display: flex; flex-wrap: wrap; gap: 8px 24px; padding: 12px 16px; margin-bottom: 16px;
            background: #f8fafc; border: 1px dashed var(--filter-border); border-radius: 10px; font-size: 13px;
        }
        .status-bar .k { color: var(--filter-muted); font-weight: 600; margin-right: 6px; }
        #errorLog { color: #b91c1c; }

        .report-container { border-radius: 12px; overflow: hidden; background: var(--filter-bg); }
        #reportView { border: none !important; border-radius: 12px; overflow: hidden; }
        #reportView iframe { border: none !important; border-radius: 12px; display: block; }
        .page-wrap {
            max-width: 1400px; margin: 0 auto; padding: 24px 20px; min-height: 100%;
            background: linear-gradient(160deg, #f8fafc 0%, #f1f5f9 100%);
        }
    </style>
</head>
<body>
<div class="page-wrap">
    <div class="filter-bar">
        <div class="filter-bar-inner">
            <!-- Region: single select -->
            <div class="filter-group">
                <span class="filter-label">Region</span>
                <div class="custom-select-wrap" id="regionWrap">
                    <div class="custom-select-trigger" id="regionTrigger" tabindex="0">
                        <span class="text">Select</span><span class="arrow"></span>
                    </div>
                    <div class="custom-select-dropdown" id="regionDropdown">
                        <div class="custom-select-option" data-value="East">East</div>
                        <div class="custom-select-option" data-value="West">West</div>
                        <div class="custom-select-option" data-value="Central">Central</div>
                    </div>
                </div>
            </div>

            <!-- Date: multi select quarters -->
            <div class="filter-group">
                <span class="filter-label">Date (quarters)</span>
                <div class="custom-select-wrap" id="dateWrap">
                    <div class="custom-select-trigger" id="dateTrigger" tabindex="0">
                        <span class="text">Select</span><span class="arrow"></span>
                    </div>
                    <div class="custom-select-dropdown" id="dateDropdown">
                        <div class="custom-select-option" data-value="Q1"><input type="checkbox">Q1</div>
                        <div class="custom-select-option" data-value="Q2"><input type="checkbox">Q2</div>
                        <div class="custom-select-option" data-value="Q3"><input type="checkbox">Q3</div>
                        <div class="custom-select-option" data-value="Q4"><input type="checkbox">Q4</div>
                    </div>
                </div>
            </div>

            <!-- Error demo -->
            <button class="demo-btn" id="invalidBtn" type="button">Apply invalid value</button>
        </div>
    </div>

    <div class="status-bar">
        <div><span class="k">Last filter event:</span><span id="eventLog">none yet</span></div>
        <div id="errorLog"></div>
    </div>

    <div class="report-container"><div id="reportView"></div></div>
</div>

<script>
(function () {
    var reportDiv = document.getElementById("reportView");
    var reportUrl = "https://analytics.zoho.in/open-view/476765000002267067";
    var vizObj = null;

    // ================= Error handling =================
    function getFilterError(err) {
        if (!err) return 'Unable to apply User Filter';
        return err.errorDesc || err.errorMsg || err.message
            || (err.response && (err.response.errorDesc || err.response.errorMsg))
            || 'Unable to apply User Filter';
    }
    function showError(msg) {
        var el = document.getElementById('errorLog');
        if (el) el.textContent = msg ? ('Error: ' + msg) : '';
    }

    // Central apply helper - every filter goes through here.
    function applyFilter(columnLabel, value, dataType, exclude) {
        if (!vizObj) return;
        showError('');
        var p = vizObj.applyUserFilter(columnLabel, value, dataType, exclude);
        if (p && typeof p.then === 'function') {
            p.then(function () {
                console.log('Applied "' + columnLabel + '"');
            }).catch(function (err) {
                showError(getFilterError(err));
            });
        }
    }

    // Surface readable errors for direct console calls too.
    window.addEventListener('unhandledrejection', function (event) {
        showError(getFilterError(event.reason));
        event.preventDefault();
    });

    // ================= USER_FILTER_CHANGE event =================
    function onUserFilterChange(eventData) {
        var filters = (eventData && eventData.appliedUserFilters) || [];
        var parts = filters.map(function (f) {
            var name = f.columnName || f.name || '';
            var val = f.displayCriteria != null && f.displayCriteria !== '' ? f.displayCriteria : '(reset)';
            return name + ': ' + val + (f.exclude ? ' [exclude]' : '');
        });
        var el = document.getElementById('eventLog');
        if (el) el.textContent = parts.length ? parts.join('  |  ') : 'none';
    }

    // ================= Custom single-select =================
    function setupSingleSelect(wrapId, triggerId, dropdownId, onSelect) {
        var wrap = document.getElementById(wrapId);
        var trigger = document.getElementById(triggerId);
        var dropdown = document.getElementById(dropdownId);
        trigger.addEventListener('click', function () { wrap.classList.toggle('open'); });
        trigger.addEventListener('keydown', function (e) {
            if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); trigger.click(); }
        });
        dropdown.querySelectorAll('.custom-select-option').forEach(function (opt) {
            opt.addEventListener('click', function () {
                var val = this.getAttribute('data-value');
                trigger.querySelector('.text').textContent = val;
                dropdown.querySelectorAll('.custom-select-option').forEach(function (o) { o.classList.remove('selected'); });
                this.classList.add('selected');
                wrap.classList.remove('open');
                onSelect(val);
            });
        });
        document.addEventListener('click', function (e) { if (!wrap.contains(e.target)) wrap.classList.remove('open'); });
    }

    // ================= Custom multi-select (quarters) =================
    function setupMultiSelect(wrapId, triggerId, dropdownId, onChange) {
        var wrap = document.getElementById(wrapId);
        var trigger = document.getElementById(triggerId);
        var dropdown = document.getElementById(dropdownId);
        function selected() {
            return Array.prototype.slice.call(dropdown.querySelectorAll('.custom-select-option.selected'))
                .map(function (o) { return o.getAttribute('data-value'); });
        }
        function refresh() {
            var vals = selected();
            trigger.querySelector('.text').textContent = vals.length ? vals.join(', ') : 'Select';
        }
        trigger.addEventListener('click', function () { wrap.classList.toggle('open'); });
        trigger.addEventListener('keydown', function (e) {
            if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); trigger.click(); }
        });
        dropdown.querySelectorAll('.custom-select-option').forEach(function (opt) {
            opt.addEventListener('click', function (e) {
                e.stopPropagation();
                this.classList.toggle('selected');
                var cb = this.querySelector('input');
                if (cb) cb.checked = this.classList.contains('selected');
                refresh();
                onChange(selected());
            });
        });
        document.addEventListener('click', function (e) { if (!wrap.contains(e.target)) wrap.classList.remove('open'); });
        return { refresh: refresh };
    }

    // ================= Init report with full userFilterConfig =================
    var reportOptions = {
        width: '100%',
        height: 600,
        // Load-time configuration (see the "Configuring User Filters at Load Time" page)
        defaultConfig: {
            userFilterConfig: {
                applyDefaultUserFilterValues: 'true',
                defaultUserFilterValues: {
                    Region: 'East',
                    Date: ['Q1', 'Q2']
                },
                // Hide the built-in filter tab; the custom controls drive filtering.
                userfilterHolderState: 'hidden'
            }
        },
        // Change event (see the "User Filter Events & Errors" page)
        onViewLoad: function () {
            vizObj.addEventListener(ZACustomEvent.USER_FILTER_CHANGE, onUserFilterChange);
        }
    };
    vizObj = new ZAnalyticsLib(reportDiv, reportUrl, reportOptions);
    vizObj.createViz();

    // ================= Wire the controls =================
    // Region - single select -> single value or RESET
    setupSingleSelect('regionWrap', 'regionTrigger', 'regionDropdown', function (val) {
        applyFilter('Region', val || 'RESET');
    });

    // Date - multi select quarters -> array, with an explicit dataType
    setupMultiSelect('dateWrap', 'dateTrigger', 'dateDropdown', function (vals) {
        applyFilter('Date', vals.length ? vals : 'RESET', 'DATE_SEASONAL_QUARTERS');
    });

    // Error demo - an unsupported quarter value rejects the Promise
    document.getElementById('invalidBtn').addEventListener('click', function () {
        applyFilter('Date', 'Q5', 'DATE_SEASONAL_QUARTERS');
    });

    window.vizObj = vizObj;
})();
</script>
</body>
</html>