how make ng-model="search" have influence on leaflet directive?

All we need is an easy explanation of the problem, so here it is.

I use leaflet-angular-directive, i successfully display objects in table and map, although i achieved filtering through searching input only affect geojson objects in table.

My aim: make filtering through searching input affect geojson objects in table and map.

My Module

   var AppMapDirectory = angular.module('DirectoryAppMap', ['ngResource', 'leaflet- directive']);

My Factory

 AppMapDirectory.factory("Directory", function($resource) {
 return $resource("json/result.json", {}, {
   get: {
       method: "GET",
       cache: true

My Controller

   AppMapDirectory.controller("DirectoryMapList", function($scope, Directory) {
   Directory.get(function(data) {

   $scope.hf_directory = data.features;

    function onEachFeature(feature, layer) {
            layer.bindPopup("<b>Wardname:</b> " + +
                "<br><b>Category:" + + "");

     angular.extend($scope, {
       geojson: {
           data: $scope.hf_directory,
           onEachFeature: onEachFeature

    angular.extend($scope, {
    defaults: {
        tileLayer: "{z}/{x}/{y}.png",
        maxZoom: 14,
        minZoom: 3
    center: {
        lat: 8.1238,
        lng: 11.8777,
        zoom: 2

My Template

 <div ng-app="DirectoryAppMap" ng-controller="DirectoryMapList">

 <li><input ng-model="" placeholder="Name" ></li>
 <li><input ng-model="" placeholder="Category"></li>



<tr ng-repeat="hf in hf_directory| filter:search">
<td>{{ }}</td>
<td>{{ }}</td>


<div leaflet id="map" center="center" defaults="defaults" geojson="geojson">


Maybe somebody could show me right direction so I know what I am doing wrong, I tried to bind search to leaflet on many different ways but without success, actually i think that it is not something that should be done on template side? But rather in options for geojson like filter? Is this the right thing to do now?

I used ng-repeat directive but then i had thousands of maps, maybe it is possible to use ng-repeat and still have only one map?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Here’s an example of how to reflect searchresults in the geojson dataset, i’ve commented the code througout to explain some things since it’s a rather large piece and understanding works best by example i think. So here it goes:

Controller HTML:

<leaflet geojson="geojson"></leaflet>
<input ng-model="search" />
<select multiple>
    <option ng-repeat="feature in">

Controller JS:

angular.module('app').controller('controller', [
    function ($scope, $http, $filter) {
        // Declare empty search model
        $ = '';
        // Declare empty geojson object
        $scope.geojson = {};
        // Fetch GeoJSON dataset
        $http.get('stations.geojson').success(function (data) {
            // Assign source data to scope
            $ = data;
            // Assign same data to the geojson object
            $ = data;
        // Start watching the search model
        $scope.$watch('search', function (newVal, oldVal) {
            // Watch gets fired on scope initialization and when empty so differentiate:
            if (newVal !== oldVal && newVal !== '') {
                // Has searchvalue, apply sourcedata, propertyname and searchstring to filter
                // and assign return value of filter to geojson 
                $ = $filter('filter')($, 'NAME', newVal);
            } else {
                // Search has been initialized or emptied, assign sourcedata to geojsonobject
                $ = $;

Filter JS:

angular.module('app').filter('filter', [function() {
    return function(geojson, searchProperty, searchValue) {
        // Declare empty GeoJSON object to store found matches
        var matches = {'type': 'FeatureCollection', 'features': []};
        // Loop over source features
        angular.forEach(geojson.features, function(featureObject, featureKey) {
            // Make sure that the assigned searchproperty exists
            if ( {
                // Source propertyvalue as lowercase;
                var property =[searchProperty].toLowerCase();
                // Search propertyvalue as lowercase;
                var search = searchValue.toLowerCase();
                // Check if searchvalue exists in sourcevalue
                if (property.indexOf(search) > -1) {
                    // Found match, push to new GeoJSON object
        // return GeoJSON object
        return matches;

Hope that helps, here’s a working example on Plunker:

After discussion in the comments about filtering on multiple properties i thought it might be handy to add that in an example, so assuming the geojson has a NAME and a LINE property:

Multiple inputs:

  <input ng-model="search.NAME" />
  <input ng-model="search.LINE" />

Change search property in scope to an object:

$ = {
  'NAME': '',
  'LINE': ''

Modified watch function:

$scope.$watch('search', function (newVal, oldVal) {
    // Protect against firing on initialization
    if (!angular.equals(newVal, oldVal)) {
        // Create copy of the sourcedata
        var geojson = angular.copy($;
        // Loop over search object
        angular.forEach(newVal, function (value, property) {
            // Only execute if value isn't empty
            if (value !== '') {
                // Apply filter and assign return data
                geojson = $filter('filter')(geojson, property, value);
        // Assign filtered geojson to geojson in scope
        $ = geojson;
    // On initialization
    } else {
        // Assign unfiltered source data to geojson in scope
        $ = $;
// Enable deep watch because we're watching an object
}, true);

Here’s the updated example on Plunker:

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from or, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply