как заставить ng-model=search влиять на директиву листовок?

Я использую leaflet-angular-directive, я успешно отображаю объекты в таблице и на карте, хотя я добился фильтрации с помощью поискового ввода, влияющего только на объекты geojson в таблице.

Моя цель: сделать так, чтобы фильтрация при поиске влияла на объекты geojson в таблице и на карте.

Мой модуль

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

Моя фабрика

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

Мой контроллер

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

   $scope.hf_directory = data.features;

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

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

    angular.extend($scope, {
    defaults: {
        tileLayer: "https://dnv9my2eseobd.cloudfront.net/v3/foursquare.map-ikj05elx/{z}/{x}/{y}.png",
        maxZoom: 14,
        minZoom: 3
    },
    center: {
        lat: 8.1238,
        lng: 11.8777,
        zoom: 2
    }
});
});

Мой шаблон

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

 <ul>
 <li><input ng-model="search.properties.name" placeholder="Name" ></li>
 <li><input ng-model="search.properties.category" placeholder="Category"></li>
 </ul>




<table>
<thead>
<tr>
<th>Name</th>
<th>Category</th>

</tr>
</thead>

<tbody>
<tr ng-repeat="hf in hf_directory| filter:search">
<td>{{ hf.properties.name }}</td>
<td>{{ hf.properties.category }}</td>

</tr>
</tbody>
</table>

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

</div>
</div>

Может быть, кто-нибудь может указать мне правильное направление, чтобы я знал, что делаю неправильно, я пытался привязать поиск к листовке разными способами, но безуспешно, на самом деле я думаю, что это не то, что следует делать на стороне шаблона? Но скорее в опциях для geojson, как фильтр? Правильно ли это сейчас?

Я использовал директиву ng-repeat, но тогда у меня были тысячи карт, может быть, можно использовать ng-repeat и иметь только одну карту?


comment
После некоторого поиска, хотя я могу ошибаться, я думаю, что я должен каким-то образом добавить маркеры задницы geojson, которые могут быть ng-repeat, тогда поиск по фильтру должен работать?   -  person IOR88    schedule 04.01.2015


Ответы (1)


Вот пример того, как отражать результаты поиска в наборе данных geojson, я прокомментировал код, чтобы объяснить некоторые вещи, так как это довольно большая часть, и я думаю, что понимание лучше всего работает на примере. Итак, вот оно:

HTML-код контроллера:

<leaflet geojson="geojson"></leaflet>
<input ng-model="search" />
<select multiple>
    <option ng-repeat="feature in geojson.data.features">
        {{feature.properties.NAME}}
    </option>
</select>

Контроллер JS:

angular.module('app').controller('controller', [
    '$scope',
    '$http',
    '$filter',
    function ($scope, $http, $filter) {
        // Declare empty search model
        $scope.search = '';
        // Declare empty geojson object
        $scope.geojson = {};
        // Fetch GeoJSON dataset
        $http.get('stations.geojson').success(function (data) {
            // Assign source data to scope
            $scope.data = data;
            // Assign same data to the geojson object
            $scope.geojson.data = 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 
                $scope.geojson.data = $filter('filter')($scope.data, 'NAME', newVal);
            } else {
                // Search has been initialized or emptied, assign sourcedata to geojsonobject
                $scope.geojson.data = $scope.data;
            }
        });
    }
]);

Фильтр 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 (featureObject.properties.hasOwnProperty(searchProperty)) {
                // Source propertyvalue as lowercase;
                var property = featureObject.properties[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
                    matches.features.push(featureObject);
                }
            }
        });
        // return GeoJSON object
        return matches;
    };
}]);

Надеюсь, это поможет, вот рабочий пример на Plunker: http://plnkr.co/edit/z02JyuGE0Y8EDrhOqzoQ?p=preview

После обсуждения в комментариях фильтрации по нескольким свойствам я подумал, что было бы удобно добавить это в пример, поэтому предположим, что у geojson есть свойство NAME и LINE:

Несколько входов:

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

Измените свойство поиска в области видимости на объект:

$scope.search = {
  'NAME': '',
  'LINE': ''
};

Модифицированная функция часов:

$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($scope.data);
        // 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
        $scope.geojson.data = geojson;
    // On initialization
    } else {
        // Assign unfiltered source data to geojson in scope
        $scope.geojson.data = $scope.data;
    }
// Enable deep watch because we're watching an object
}, true);

Вот обновленный пример на Plunker: http://plnkr.co/edit/OOx5DebtKXBfYqJ2Da3a?p=preview< /а>

person iH8    schedule 07.01.2015
comment
У меня есть вопрос, я обнаружил, что mapbox.js намного проще в использовании, если я хочу сделать решение из окна карты доступным в листовке, это означает некоторую работу с библиотекой? Там у вас есть директива mapbox, в которой есть несколько вложенных директив, таких как маркеры, и она наследует, я думаю, директиву ng-repeat, поэтому ее можно использовать в mapbox и работать с поиском модели ng без каких-либо наблюдателей и фильтров, ваше решение отличное, я правильно перевариваю ваш код;) - person IOR88; 07.01.2015
comment
Это очень оффтоп / вне контекста для этого вопроса. Я рекомендую вам начать новый вопрос и пометить его с помощью Mapbox, а также Leaflet, чтобы другие тоже могли помочь или найти его, когда у них возникнет тот же вопрос. Комментарии предназначены не для того, чтобы задавать новые вопросы, а только для того, чтобы попросить разъяснений по текущему вопросу или ответу. - person iH8; 07.01.2015
comment
Если есть какое-то выражение, которое позволяет добавить несколько свойств в качестве searchProperty? Например, «имя» и «адрес»? - person IOR88; 07.01.2015
comment
Конечно, вы можете легко написать еще один фильтр $filter('filter')($scope.data, newValue) для использования объекта поиска из вашей области видимости, что-то вроде $scope.search = {'name': '', 'city': ''} вместо одной строки. Они могут быть подключены к нескольким входам в вашем шаблоне. Фильтр станет немного сложнее, но его можно легко сделать. Вы также можете дважды запустить текущий фильтр в функции просмотра. Это вопрос предпочтений. - person iH8; 07.01.2015
comment
Я отредактировал свой исходный ответ и добавил пример использования фильтра для нескольких свойств. Надеюсь, это поможет. - person iH8; 08.01.2015