如何从子元素初始化AngularJS指令模型?

时间:2013-03-28 18:25:17

标签: asp.net-mvc angularjs angularjs-directive

我正在尝试使用子元素初始化AngularJS指令中的一些数据。在这种情况下,<map>元素将替换为使用传单连接的<div>。我试图弄清楚指令compilelink函数中是否有某种方法可以从声明的子元素中填充markers集合,如下所示:

<div ng-app="dashboard">
<div ng-controller="DashboardCtrl">
    <map id="devicemap" tile-handle="test.map-fy18v14h" min-zoom="3" max-zoom="9" markers="markers">
        <marker lat="44" lng="-88.5" description="From the Server (Razor)" />
        <marker lat="44.1" lng="-88.6" description="From the Server 2 (Razor)" />
    </map>
</div>

在指令中,我想迭代<marker>元素来填充集合。这应该在编译中发生吗?或者,我是否误导我可以在插入实际模板之前访问我的“假DOM”?

module.directive('map', function () {
return {
    restrict: "E",
    replace: true,
    scope: {
        markers: "=markers"
    },
    template: '<div class="map"></div>',
    link: function link(scope, elm, attributes) {
        var map = L.map(attributes.id, {
            dragging: true,
            zoomAnimation: true
        }).setView([45.505, -88.09], 6);
        L.tileLayer('http://{s}.tiles.mapbox.com/v3/' + attributes.tileHandle + '/{z}/{x}/{y}.png', {
            attribution: "<a href='http://mapbox.com/about/maps' target='_blank'>Terms & Feedback</a>",
        }).addTo(map);

        // This is where I am stuck... is there a way to get the "marker" elements?   
        // the following does not work...
        var markerElements = elm.children('marker');  

        // now would like to loop over markerElements, grab the attributes and add them 
        // to the map (and/or the markers collection).

    };
});

我可以使用ajax调用填充标记,但是,这种技术可以让我在首次请求页面时预先填充服务器上的数据。

2 个答案:

答案 0 :(得分:0)

好的,有了Mark Rajcok的提示,我想出了一个解决方案。这允许我使用在服务器上生成的自定义HTML元素在地图上设置标记。我需要使用list变量来存储compile函数中收集的数据。不确定是否有更简洁的方法来使用Angular。

<强> HTML /剃须刀

<div ng-app="dashboard">
    <div ng-controller="DashboardCtrl">
        <map id="devicemap" tile-handle="example.map-fy18v14h" min-zoom="3" max-zoom="9" markers="markers">
        @foreach (var location in Model.Locations)
        {
           <marker lat="@location.Lat" lng="@location.Lng" description="@location.Description" ></marker>                                   
        }
        </map>
     </div>
</div>

<强>控制器

var module = angular.module('dashboard', ['map-directive']);
module.controller("DashboardCtrl", function ($scope, $http) {
     $scope.markers = [];
});

<强>指令

var mapDirective = angular.module("map-directive", []);

mapDirective.directive('map', function () {

    var list = [];

    function link (scope, elm, attributes) {
        var map = L.map(attributes.id, {
            dragging: true,
            zoomAnimation: true
        }).setView([45.505, -88.09], 6);

        scope.markers = list;

        L.tileLayer('http://{s}.tiles.mapbox.com/v3/' + attributes.tileHandle + '/{z}/{x}/{y}.png', {
            attribution: "<a href='http://mapbox.com/about/maps' target='_blank'>Terms & Feedback</a>",
        }).addTo(map);

        scope.$watch('markers', function (newValue, oldValue) {
            if (newValue)
                angular.forEach(scope.markers, function (marker) {
                    L.marker([marker.lat, marker.lng], { draggable: marker.draggable }).addTo(map).bindPopup(marker.description);
                });
        });
    }

    return {
        restrict: "E",
        scope: {
            markers: "=markers"
        },

        compile: function(tElement, tAttrs, transclude) {

            console.log(tElement);
            console.log(tElement.find("marker"));

            var markers = tElement.find("marker");


            angular.forEach(markers, function (marker) {
                list.push({ lat: marker.attributes.lat.value, lng: marker.attributes.lng.value, description: marker.attributes.description.value});
            });

            var htmlText = '<div class="map" id="' + tAttrs.id + '" ></div>';
            tElement.replaceWith(htmlText);
            return link;
        }
    };

});

答案 1 :(得分:0)

实际上你可以使用templateUrl的derective。 只需将ng-transclude包含在那里的任何元素上,它就会将所有原始子元素都作为自己的元素。 然后在链接函数中,您可以读取这些DOM元素,执行任何操作并清理它们。