javascript 如何在传单标记弹出窗口中使用 Angular 指令 ng-click 和 ng-class

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17662551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 09:07:17  来源:igfitidea点击:

How to use Angular directives ng-click and ng-class inside Leaflet marker popup

javascriptangularjsleaflet

提问by Ashley

I'm using Angular.JS and Leaflet.JS for a map in my location that has map markers with popups binded to them. I need to use a span with two different icons (one shown in code below) that you can click to call different functions and with ng-class to change the class if certain conditions are met. This is my code:

我将 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>');

However when I inspect the element I get this:

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

<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>

The ng-click should send that function both the specific object and the array of objects but when I click the icon nothing happens. In my research I found that the popup prevents event propagation (more infobut I'm not sure how to override it or a fix to get it to work with angular. Would anyone have an idea of how to accomplish this?

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

UPDATE:

更新:

Since ng-click/class evaluate a string I fixed the variables to be like this:

由于 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>');

The html then comes out correctly:

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>

However when I click the icon nothing happens and it doesn't look like the functions are being called. Anyone have any clue why this would happen?

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

回答by Xowap

Your issue comes from the fact that you are manually creating some DOM, which was not compiled by AngularJS.

您的问题来自于您手动创建了一些不是由 AngularJS 编译的 DOM。

In those cases, you have to manually compile and link the element.

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

The code would look like this:

代码如下所示:

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]);

Here I take your HTML string, and I start by transforming it into DOM. Because AngularJS eats DOM, not strings.

在这里,我使用您的 HTML 字符串,然后将其转换为 DOM。因为 AngularJS 吃 DOM,而不是字符串。

angular.element(html)

Then, I compile this DOM into a link function, using the $compile service.

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

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

When executed, this function will return a jQuery DOM tree fully controlled by Angular, running in the scope you give to it as argument. This is what I do here

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

linkFunction(newScope)

Please note that the scope I give is a child scope of $scope. Without doing this, you would share the same scope between all popups, and this would not be a good idea. Creating the new scope was done in the var declaration

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

newScope = $scope.$new()

From that you can get the actual DOM node

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

linkFunction(scope)[0]

And pass it to Leaflet

并将其传递给 Leaflet

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

And you're done!

大功告成!

For more info, please refer to the compilerdoc.

有关更多信息,请参阅编译器文档。

EDIT: rectified issues regarding scope

编辑:纠正了有关范围的问题

回答by David

You can use the new support for Angular content in angular-leaflet-directive:

您可以在 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; },          
});

回答by shi11i

I found this answer help for mapbox-gl-js and angular:

我发现这个答案对 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);

Enable ng-click on a popup (mapbox)

在弹出窗口(地图框)上启用 ng-click

回答by Bwyss

I'm a bit late to the topic, but I had a similar situation and wanted to share my solution.

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

Suppose you have some html that you want to add into your popup, simply add an 'id' into it.

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

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

now all you need to do is this:

现在你需要做的就是:

var popupElement = $('#popup'); // grab the element (make sure that it exists in the DOM)
popupElement = $compile(popupElement)($scope); // let angular know about it

回答by SylvainAr

I arrived on this post because I was looking for a solution of this problem on Ionic/Cordova (map integration on a mobile app).

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

The problem is the fact that $compute function doesn't seems to work, because it runs with a lite version of jQuery. So the only way, and clearly the simpliest, to make it work is with the code proposed by David (Thank you so much mate !).

问题在于 $compute 函数似乎不起作用,因为它使用 jQuery 的精简版运行。所以唯一的方法,而且显然是最简单的,让它工作的是大卫提出的代码(非常感谢你的伙伴!)。

In my code, it looks like this :

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

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

Hope this could help!

希望这会有所帮助!

回答by tor9ado

I worked on this particular type of problem, to instantiate a function against a click inside a popup. I was using angular-leaflet-directive where I could not do a $compile as it was already inside a $compile, and would create a circular reference. What I did was the following.

我致力于解决这种特殊类型的问题,针对弹出窗口内的点击实例化一个函数。我在使用 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']
                        }
                    };

And below that, the function viewDetail() was called

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

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

So I had to use traditional javascript inside angular to avoid the complicacy of circular linking.

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