17

我正在使用 Angular.JS 和 Leaflet.JS 作为我所在位置的地图,该地图具有绑定到它们的弹出窗口的地图标记。我需要使用一个带有两个不同图标(一个在下面的代码中显示)的跨度,您可以单击它们来调用不同的函数,并在满足某些条件时使用 ng-class 来更改类。这是我的代码:

var marker = L.marker([51.5, -0.09], {icon: blueIcon}).bindPopup('<br><span ng-class="thumbsUpClass(' + hotelsSelectedDates[i]['hotels'][s] + ')" ng-click="addChoice(' + hotelsSelectedDates[i]['hotels'][s] + ',' + hotels + ')"><span class="popup-container"><span class="icon-stack thumbs-up-stack"><i class="icon-sign-blank icon-stack-base"></i><i class="icon-thumbs-up"></i></span></span></span>');

但是,当我检查元素时,我得到了这个:

<span ng-class="thumbsUpClass([object Object])" ng-click="addChoice([object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object])"><span class="popup-container"><span class="icon-stack thumbs-up-stack"><i class="icon-sign-blank icon-stack-base"></i><i class="icon-thumbs-up"></i></span></span></span>

ng-click 应该向该函数发送特定对象和对象数组,但是当我单击图标时没有任何反应。在我的研究中,我发现弹出窗口阻止了事件传播(更多信息,但我不确定如何覆盖它或修复它以使其与角度一起使用。有人知道如何实现这一点吗?

更新:

由于 ng-click/class 评估一个字符串,我将变量固定为:

$scope.item = hotelsSelectedDates[i]['hotels'][s]
$scope.set = hotels
var marker = L.marker([51.5, -0.09], {icon: blueIcon}).bindPopup('<br><span ng-class="thumbsUpClass(item)" ng-click="addChoice(item,set)"><span class="popup-container"><span class="icon-stack thumbs-up-stack"><i class="icon-sign-blank icon-stack-base"></i><i class="icon-thumbs-up"></i></span></span></span>');

html 然后正确显示:

<span ng-class="thumbsUpClass(item)" ng-click="addChoice(item,set)"><span class="popup-container"><span class="icon-stack thumbs-up-stack"><i class="icon-sign-blank icon-stack-base"></i><i class="icon-thumbs-up"></i></span></span></span>

但是,当我单击该图标时,什么也没有发生,并且看起来没有调用函数。任何人都知道为什么会发生这种情况?

4

6 回答 6

28

您的问题来自您手动创建一些 DOM 的事实,这些 DOM 不是由 AngularJS 编译的。

在这些情况下,您必须手动编译和链接元素。

代码如下所示:

var html = '<br><span ng-class="thumbsUpClass(item)" ' +
    'ng-click="addChoice(item,set)"><span class="popup-container"><span ' +
    'class="icon-stack thumbs-up-stack"><i class="icon-sign-blank ' +
    'icon-stack-base"></i><i class="icon-thumbs-up"></i></span></span></span>',
    linkFunction = $compile(angular.element(html)),
    newScope = $scope.$new();

newScope.item = hotelsSelectedDates[i]['hotels'][s]
newScope.set = hotels
var marker = L.marker([51.5, -0.09], {icon: blueIcon}).bindPopup(linkFunction(newScope)[0]);

在这里,我获取您的 HTML 字符串,并首先将其转换为 DOM。因为 AngularJS 吃的是 DOM,而不是字符串。

angular.element(html)

然后,我使用 $compile 服务将此 DOM 编译为链接函数。

linkFunction = $compile(angular.element(html));

执行时,此函数将返回一个完全由 Angular 控制的 jQuery DOM 树,并在您作为参数提供给它的范围内运行。这就是我在这里所做的

linkFunction(newScope)

请注意,我给出的范围是 $scope 的子范围。如果不这样做,您将在所有弹出窗口之间共享相同的范围,这不是一个好主意。创建新范围是在 var 声明中完成的

newScope = $scope.$new()

从那里你可以得到实际的 DOM 节点

linkFunction(scope)[0]

并将其传递给 Leaflet

.bindPopup(linkFunction(newScope)[0]);

你完成了!

有关详细信息,请参阅编译器文档。

编辑:关于范围的更正问题

于 2013-12-05T13:30:21.137 回答
10

您可以在 angular-leaflet-directive 中使用对 Angular 内容的新支持:

var html = '<br><span ng-class="thumbsUpClass(item)" ' +
    'ng-click="addChoice(item,set)"><span class="popup-container"><span ' +
    'class="icon-stack thumbs-up-stack"><i class="icon-sign-blank ' +
    'icon-stack-base"></i><i class="icon-thumbs-up"></i></span></span></span>';

... 

$scope.markers.push( { lat: ...,
                       lng: ...,
                       message: html,
                       getMessageScope: function() { return $scope; },          
});
于 2015-01-14T02:54:08.747 回答
1

我为 mapbox-gl-js 和 angular 找到了这个答案帮助:

var html = '<button ng-click="fn()">Click Me</button>';
var compiledHtml = $compile(html)($scope);
var popup = new mapboxgl.Popup()
 .setLngLat([-91.874, 42.760])
 .setDOMContent(compiledHtml[0])
 .addTo(map);

在弹出窗口上启用 ng-click (mapbox)

于 2017-04-28T19:01:44.290 回答
0

我研究了这种特殊类型的问题,针对弹出窗口内的点击实例化一个函数。我正在使用 angular-leaflet-directive 无法执行 $compile 因为它已经在 $compile 中,并且会创建一个循环引用。我所做的是以下。

$scope.markers[$scope.asset_table[imc]['asset']['_id']['$oid']]={
                        lat:$scope.asset_table[imc]['last_data']['loc']['coordinates'][1],
                        lng:$scope.asset_table[imc]['last_data']['loc']['coordinates'][0],
                        focus:true,
                        message:"<h4>"+$scope.asset_table[imc]['asset']['name']+"</h4>
                        <span class='btn btn-danger' 
                        onclick='detailView()';>View Details</span>",
                        //message: linkFunction, /*I discarded this as it was creating circular reference*/
                        icon: {
                            iconUrl: $scope.icon,
                            iconSize: [30, 30],
                            iconAnchor: [15, 15],
                            popupAnchor: [0, 0],
                            shadowUrl: $scope.icon,
                            shadowSize:[0,0],
                            iconAngle:$scope.asset_table[imc]['last_data']['bearing']
                        }
                    };

在此之下,函数 viewDetail() 被调用

detailView = function(){
    //alert("Test");
    $rootScope.$broadcast('asset.details',$scope.asset_table);
}

所以我不得不在 Angular 中使用传统的 javascript 来避免循环链接的复杂性。

于 2014-04-26T06:49:02.757 回答
0

我对这个话题有点晚了,但我有类似的情况,想分享我的解决方案。

假设您有一些要添加到弹出窗口中的 html,只需在其中添加一个“id”即可。

var html = '<a id="popup" href="" ng-model="featureSelected" ng-click="cherryPickPin(featureSelected)">cherry pick this pin</a>';

现在你需要做的就是:

var popupElement = $('#popup'); // grab the element (make sure that it exists in the DOM)
popupElement = $compile(popupElement)($scope); // let angular know about it
于 2015-06-12T16:16:18.377 回答
0

我来到这篇文章是因为我在Ionic/Cordova(移动应用程序上的地图集成)上寻找这个问题的解决方案。

问题是 $compute 函数似乎不起作用,因为它使用 jQuery 的精简版运行。因此,使其工作的唯一方法,显然也是最简单的方法是使用 David 提出的代码(非常感谢队友!)。

在我的代码中,它看起来像这样:

$scope.map.markers[i] = {
    lat: parseFloat(place.latitude),
    lng: parseFloat(place.longitude),
    message: htmlPopupContent,
    getMessageScope: function() { return $scope; },
    focus: true,
    draggable: false
};

希望这会有所帮助!

于 2016-03-28T17:54:03.393 回答