I want to display a dynamic generated HTML in uib-popover, and it's shown when a <i> is clicked in each column header of uib-grid. The ng directives and variables also need to be active, such as ng-click, $scope etc.
I tried to use the headerCellTemplate in each column definition of uib-grid for displaying the<i>tag, and I passed a dynamic generated HtML to each column definition, so that I can get it in the headerCellTemplate with col.displayName.popoverTemplate, It works fine. But I can't pass any variables in to popover use $scope, and ng-click don't work at all. Someone said I need to compile the HTML or use the uib-popover-template, how do I pass params to uib-popover-html or there is another way.
THANKS!
columnDefs
columnDefs.push({
name:'columnViewData._name',
displayName:{//use this file to pass params into uib-grid headers
displayName:'columnName',
popoverTemplate:generatePopoverTemplate(),//template should be shown in popover for this column header
customerScope:$scope//current scope, I hope popover can access it
},
width:100,
enableColumnMenu:false,
pinnedLeft:true,
headerCellTemplate:generateUIGridHeaderTemplate('name',0)
});
Column header template:
var generateUIGridHeaderTemplate = function(columnName,type){
return "\
<div role=\"columnheader\" ng-class=\"{ 'sortable': sortable }\" ui-grid-one-bind-aria-labelledby-grid=\"col.uid + '-header-text ' + col.uid + '-sortdir-text'\" aria-sort=\"{{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending' : (!col.sort.direction ? 'none' : 'other'))}}\">\
<div style=\"margin-top:0.3em;\">\
<div style=\"display:inline;\" role=\"button\" tabindex=\"0\" class=\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\" col-index=\"renderIndex\" title=\"TOOLTIP\">\
<span class=\"ui-grid-header-cell-label\" ui-grid-one-bind-id-grid=\"col.uid + '-header-text'\">\
{{ col.displayName.displayName CUSTOM_FILTERS }}\
</span> \
<span ui-grid-one-bind-id-grid=\"col.uid + '-sortdir-text'\" ui-grid-visible=\"col.sort.direction\" aria-label=\"{{getSortDirectionAriaLabel()}}\">\
<i ng-class=\"{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc, 'ui-grid-icon-blank': !col.sort.direction }\" title=\"{{isSortPriorityVisible() ? i18n.headerCell.priority + ' ' + ( col.sort.priority + 1 ) : null}}\" aria-hidden=\"true\">\
</i> \
<sub ui-grid-visible=\"isSortPriorityVisible()\" class=\"ui-grid-sort-priority-number\">\
{{col.sort.priority + 1}}\
</sub>\
</span>\
</div>\
<i style=\"margin-left:-1em;\" class=\"glyphicon glyphicon-filter\" popover-placement='bottom' uib-popover-html=\"col.displayName.popoverTemplate\" popover-title=\"Filter\" popover-append-to-body=\"true\">\
</i>\
<!-- above line is the popover togger shown in the column header-->\
</div>\
<div role=\"button\" tabindex=\"0\" ui-grid-one-bind-id-grid=\"col.uid + '-menu-button'\" class=\"ui-grid-column-menu-button\" ng-if=\"grid.options.enableColumnMenus && !col.isRowHeader && col.colDef.enableColumnMenu !== false\" ng-click=\"toggleMenu($event)\" ng-class=\"{'ui-grid-column-menu-button-last-col': isLastCol}\" ui-grid-one-bind-aria-label=\"i18n.headerCell.aria.columnMenuButtonLabel\" aria-haspopup=\"true\">\
<i class=\"ui-grid-icon-angle-down\" aria-hidden=\"true\">\
\
</i>\
</div>\
<div ui-grid-filter>\
</div>\
</div>"}
Popover template
var generatePopoverTemplate = function(){
var t = $sce.trustAsHtml('<a class="btn" ng-click="alert(\'asd\')">asd</a>');
$compile(t)($scope);
return t;
}
I solved my question :)
Generate the popover template and put it in to $compileCache with an Id then uib-popover-template property can find it and ng works fine.
Related
Array used in repeat for loop
let loopArr = ["item.name + ' /'+ item.DisplayName? item.DisplayName: item.otherDisplayName",
"item.description + ' /'+ item.anotherDescription"]
Template
<div repeat.for = item of data">
<div repeat.for = "row of loopArr">
<span textcontent.bind="renderRow(row, item)></span>
</div>
</div>
Component method
renderRow(row, item){
return eval(row)
}
Actually I wanted to display like below in template
<div repeat.for = item of data">
<div repeat.for = "row of loopArr">
<span>${item.name + ' /'+ item.DisplayName? item.DisplayName: item.otherDisplayName} </span>
<span>${item.description + ' /'+ item.anotherDescription} </span>
</div>
</div>
Since I wanted to loop through dynamic loopArr, instead of using eval to convert from string to value, is there any better way to compute the value from string? Also, eval doesnt work for multiline statements, is there any other approach/way to handle the above problem?
How to convert string to value and display in aurelia template?
Any help would be appreciated!
I'm not sure why you're adding the logic in string format and using eval. You could directly add it to the template and display it:
<div repeat.for="item of data">
<span>${item.name + '/' + (item.DisplayName ? item.DisplayName: item.otherDisplayName)}</span>
<span>${item.description + ' / '+ item.anotherDescription} </span>
</div>
Let's assume you have a list of custom string formats and you are importing them from another file. You could create an array of functions instead of array of strings. This is much better way of deferring the string creation than running eval
displayTemplates = [
item => item.name + '/' + (item.DisplayName ? item.DisplayName: item.otherDisplayName),
item => item.description + '/'+ item.anotherDescription
]
and then in the template:
<div repeat.for="item of data">
<template repeat.for="func of displayTemplates">
<span>${ func(item) }</span> <!-- call each func on item object -->
</template>
</div>
Also, there is a logical error in your string format. + operator has higher precedence compared to the ternary operator.
So,
item.name + '/' + item.DisplayName ? item.DisplayName : item.otherDisplayName
is actually evaluated as
(item.name + '/' + item.DisplayName) ? item.DisplayName : item.otherDisplayName
So, this expression will always evaluate to item.DisplayName because item.name + '/' + item.DisplayName will never be falsy.
You need to add () around the ternary operation:
item.name + '/' + (item.DisplayName ? item.DisplayName: item.otherDisplayName)
// OR
item.name + '/' + (item.DisplayName ?? item.otherDisplayName)
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 4 years ago.
I have been assigned to update a classic asp website with a Prestashop template called Autotune Responsive Prestashop Theme. My client wants all the ajax bells and whistles they see online in Template Monster. Template Monster made static html files for my client from this template which includes all the custom Prestashop javascript libraries. So far I am unable to use these custom Prestashop jquery/ajax libaries as they were intended so I have to write my own code to paginate, add to cart, show item popup, etc. Everything works great except for appending html. For example, pagination. When I view a list of parts in grid view and I click to append nine more parts, the html gets appended OK but onclick events to the Add To Cart button and "eye" icon popup are dead for the new items that were appended. Mouse over events are OK. Same issue when I append html to the cart popup - I see the added cart items in the cart popup but the "x" (delete) won't work when clicked although the color changes when moused over. It's as if I need to update something after appending. I'm stumped. Here is the pagination code:
$(function() {
$('#infiniteScrollMore').click(function(){
var numItems = parseInt($('#NumItems').text());
var pageNbr = parseInt($('#PageNbr').text()) + 1;
$('#PageNbr').text(pageNbr);
$.get('AppendParts.asp?PageNbr=' + pageNbr + '&NumItems=' + numItems,function (data) {
$('.product_list').append(data);
numNextItems = parseInt(numItems) - (parseInt(pageNbr) * 9);
if (parseInt(numNextItems) >= 9) numNextItems = 9;
setTimeout(function(){$('#NumNextItems').text(' (' + numNextItems + ')')},2000);
if ((parseInt(pageNbr) * 9) >= parseInt(numItems))
{
$('#infiniteScrollMore').hide();
setTimeout(function(){$('#NewSearchButton').show();},2000);
}
});
});
});
I am just using .append to append html to the product_list ul. AppendParts.asp writes the html, which is...
<li class="ajax_block_product">
<div class="product-container" itemscope itemtype="https://schema.org/Product">
<div class="left-block">
<div class="product-image-container">
<div class="tmproductlistgallery rollover">
<div class="tmproductlistgallery-images opacity">
<a class="product_img_link cover-image" href="product.asp?PartNbr=<%=pageCache("PartNbr")%>&StockNbr=<%=pageCache("StockNbr")%>&ProductCode=<%=pageCache("ProductCode")%>&MachineType=<%=pageCache("MachineType")%>&Model=<%=pageCache("Model")%>&Category=<%=pageCache("Category")%>&SubCategory=<%=pageCache("SubCategory")%>" title="<%=pageCache("Description") & " " & pageCache("Make") & " " & pageCache("PartNbr") & " " & pageCache("Class")%>" itemprop="url">
<img class="img-responsive" src="http://<%=theImage%>" alt="" title="<%=pageCache("Description") & " " & pageCache("Make") & " " & pageCache("PartNbr") & " " & pageCache("Class")%>">
</a>
<a class="product_img_link rollover-hover" href="product.asp?PartNbr=<%=pageCache("PartNbr")%>&StockNbr=<%=pageCache("StockNbr")%>&ProductCode=<%=pageCache("ProductCode")%>&MachineType=<%=pageCache("MachineType")%>&Model=<%=pageCache("Model")&Category=<%=pageCache("Category")%>&SubCategory=<%=pageCache("SubCategory")" title="<%=pageCache("Description") & " " & pageCache("Make") & " " & pageCache("PartNbr") & " " & pageCache("Class")%>" itemprop="url">
<img class="img-responsive" src="http://<%=theImage%>" alt="" title="<%=pageCache("Description") & " " & pageCache("Make") & " " & pageCache("PartNbr") & " " & pageCache("Class")%>">
</a>
</div>
</div>
<div class="functional-buttons">
<div class="qv-wrap">
<a class="quick-view" data-id="<%=pageCache("ProductCode") & ":" & pageCache("StockNbr") & ":" & pageCache("PartNbr")%>" href="#" onclick="return false;" data-fancybox-type="ajax" data-type="ajax" data-href="#" title="Quick View"></a>
</div>
<div class="compare">
<a class="add_to_compare" href="product.asp?PartNbr=<%=pageCache("PartNbr")%>&StockNbr=<%=pageCache("StockNbr")%>&ProductCode=<%=pageCache("ProductCode")%>&MachineType=<%=pageCache("MachineType")%>&Model=<%=pageCache("Model")%>&Category=<%=pageCache("Category")%>&SubCategory=<%=pageCache("SubCategory")%>" data-id-product="<%=pageCache("ProductCode") & ":" & pageCache("StockNbr") & ":" & pageCache("PartNbr")%>" title="Detailed View"></a>
</div>
</div>
... abbreviated a bit. Here is the fancybox code:
$(function() {
$('.quick-view').click(function(){
var idStrArray = $(this).attr('data-id');
var idStr = idStrArray.split(':');
var productCode = idStr[0];
var stockNbr = idStr[1];
var partNbr = idStr[2];
$.fancybox({
'closeClick': true,
'hideOnContentClick': true,
'padding': 0,
'width': 1021,
'autoDimensions': false,
'height': 500,
'type': 'iframe',
'tpl': {wrap: '<div class="fancybox-wrap fancybox-quick-view" tabIndex="-1"><div class="fancybox-skin"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div></div>'},
'href': 'product-popup.asp?PartNbr=' + partNbr + '&ProductCode=' + productCode + '&StockNbr=' + stockNbr,
'beforeClose': function() {}
}
});
});
});
What am I missing?
You have to the event trigger like this -
$( "body" ).on( "click", "p", function() {
alert( $( this ).text() );
});
Use jQuery .on() method. Read the doc
<div>
<ul ng-repeat="items in allcategories">
<p class="padding">{{ items.title }}</p>
<ion-slide-box show-pager="false" on-slide-changed="slideHasChanged($index)" class="padding">
<ion-slide ng-repeat="ite in allvodsforcategory">
<img ng-src="{{ ite.image }}">
</ion-slide>
</ion-slide-box>
</ul>
</div>
$http.get('http://api.com?user=' + $scope.apiusername + '&pass=' + $scope.apipassword + '&id=' . items.id).success(function(data) {
$scope.allvodsforcategory = data.videos;
});
$http.get('http://api.com?user=' + $scope.apiusername + '&pass=' + $scope.apipassword).success(function(data) {
$scope.allcategories = data.categories;
});
There is my code you can see the first ng-repeat on the ul item that is listing categories in side I want to list images no you can see the second ng-repeat on the ion-slide now I need to pass the items.id to the controller then put it into the url but I can not find a way to do that please help my all help is appreciated THANK YOU
If my understanding of your question is correct, I think that what you would have to do is create an isolate scope for your custom directive (ion-slide). This will allow you to pass the item id as an attribute. And it will be available to use in your controller. What I mean is:
...
.directive(ionSlide, function(...) {
return {
scope: {
itemId: '#',
},
.... // Other things
};
});
// In your html you would then have
...
<ion-slide item-id="{{item.id}}" ng-repeat="ite in allvodsforcategory">
<img ng-src="{{ ite.image }}">
</ion-slide>
...
// And in your controller,
...
.controller(function($scope, ...){
var id = $scope.itemId; // you have your id here.
$http.get('http://api.com?user=' + $scope.apiusername + '&pass=' + $scope.apipassword + '&id=' id).success(function(data) {
$scope.allvodsforcategory = data.videos;
});
});
Hope this helps.
I have this Angular expression in my view:
<span ng-if="{{list.StoreList ? (list.StoreList.length ' Products)' : '(0 Products)'}}"> </span>
So if I have any items in the StoreList then I'll display the count, otherwise I'll just show 0 products.
I'm getting unexpected expecting error from Angularjs.
How can I solve this?
Try with:
<span ng-if="list.StoreList">{{'(' + list.StoreList.length + ' Products)'}}</span>
<span ng-if="!list.StoreList">(0 Products)</span>
This is not formatted correctly
<span ng-if="{{list.StoreList ? (list.StoreList.length ' Products)' : '(0 Products)'}}"> </span>
should probably be
<span ng-if="{{ list.StoreList ? '(' + list.StoreList.length + ' Products)' : '(0 Products)'}}"> </span>
Have searched for a solution to this but am coming up blank. I'm trying to set a data attribute and access it within the fancyBox options.
My anchor links looks like this:
<a class="expand" rel="gallery" href="/assets/images/larger-image.png" data-source="Some string" data-id="Some number">
<img src="blah.jpg" />
</a>
And my JS:
$(".expand").fancybox({
'padding' : 0,
'tpl' : {
image : '<img class="fancybox-image" src="{href}" alt="" />'
}
});
What I'd like to be able to do is access those data-attributes inside the tpl option.
$(".expand").fancybox({
'padding' : 0,
'tpl' : {
image : '<h2>' + $(this.element).data('source') + '</h2><img class="fancybox-image" src="{href}" alt="" /><h3>' + $(this.element).data('id') + '</h3>'
}
});
I can't access this.element in that context; is there an elegant way to achieve this?
Well, the tpl is used to format specific elements of the fancybox structure so this
'tpl' : {
image : '<h2>' + $(this.element).data('source') + '</h2><img class="fancybox-image" src="{href}" alt="" /><h3>' + $(this.element).data('id') + '</h3>'
}
it's a bit odd since you are adding elements that are not part of the image template (normally you would use it to add classes or other attributes, etc.)
Anyways, if this is what you want, you first need to use a fancybox callback to have access to the data attributes ( $(this.element) can only be accessed inside a callback ).
Then you may need to use the jQuery.extend() method to modify the fancybox template on the fly (from within the afterLoad callback) like :
$(".expand").fancybox({
afterLoad: function () {
$.extend(this, {
tpl: {
image: '<h2>' + $(this.element).data('source') + '</h2><img class="fancybox-image" src="{href}" alt="" /><h3>' + $(this.element).data('id') + '</h3>'
}
});
}
});
See JSFIDDLE