title: Kendo Grid Client-Side Custom Filters
body: <p>Let's assume I have a database with 2 tables. First table is location codes. Second table is event records. Event records contain a location code ID.</p>
  <p><em>Edit: tables weren't working apparently, so I took a screenshot of the preview</em>
  <a href="https://i.stack.imgur.com/5D8TV.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/5D8TV.png" alt="tables" /></a></p>
  <p>And I am using Kendo Grid to display the data. On the server when I get the data I package it so that my location column is stored as an array.</p>
  <p><code>$rowdata['location'] = array('location_id' =&gt; $data['location_id'], 'location_code' =&gt; $data['location_code']);</code></p>
  <p>I use a template in my grid to display only the code.</p>
  <p>The trouble that I am having is when using client-side filtering on this or other similarly formatted columns. I am aware that this would be much easier to accomplish using server-side filtering, however there are reasons why this is not being used.</p>
  <p>What I am attempting to do is to modify the operator value during the filter event of the grid.</p>
  <pre><code>var customOperators = {};
  $('#grid').kendoGrid({
      ...
      filterMenuOpen: function (e) {
          // since the custom operator does not exist, no operator is selected when the menu is re-opened. select the one last used for this field.
          if (customOperators.hasOwnProperty(e.field)) {
              $(e.container.find('select[data-bind=&quot;value: filters[0].operator&quot;]')).data('kendoDropDownList').value(customOperators[e.field]);
          }
      },
      filter: filterOpChange
  });
  
  function filterOpChange(e) {
      if (e.filter === null) {
          if (customOperators.hasOwnProperty(e.field)) {
              delete customOperators[e.field];
          }
          return;
      }
  
      let oldOp = e.filter.filters[0]['operator'];
      if (typeof window[e.field + '_' + oldOp] === &quot;function&quot;) {
          customOperators[e.field] = oldOp; // store the old operator in an object to re-select it from the list when the filter menu opens
          e.filter.filters[0]['operator'] = window[e.field + '_' + oldOp]; // assign function named [field_name]_[operator] to the operator
      }
  }
  
  // eq
  function location_eq(itemVal, filterVal) {
      return (itemVal &amp;&amp; itemVal.location_id !== null &amp;&amp; filterVal !== null &amp;&amp; parseInt(itemVal.location_id) === parseInt(filterVal));
  }
  
  // neq
  function location_neq(itemVal, filterVal) {
      return (itemVal &amp;&amp; itemVal.location_id !== null &amp;&amp; filterVal !== null &amp;&amp; parseInt(itemVal.location_id) !== parseInt(filterVal));
  }
  </code></pre>
  <p>And this works. It filters as I expect it to. However, there is a problem if I attempt to change the filter for this field. If I change the filter menu from <em>equals</em> to <em>does not equal</em> I get a JavaScript error. In Chrome the error message is:
  <a href="https://i.stack.imgur.com/umdQy.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/umdQy.png" alt="chrome error message" /></a></p>
  <p>In Firefox the error message is (cut off the last file which is the file that has the grid on it):
  <a href="https://i.stack.imgur.com/2lCpG.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/2lCpG.png" alt="firefox error message" /></a></p>
  <p>The reason that I am using custom operators instead of a standard dropdown list is because I want to be able to filter based only on the text values so that a user can filter for &quot;locA&quot; and locA_1, locA_2, and locA_3 will all be displayed. The sample code I provided does not do this exactly, instead it looks at the ID, but that was easier to include here. I would appreciate any help with resolving the issue of applying a filter to a column that uses objects for values whether that means fixing my current error or going about it in a different way so long as it stays client-side.</p>