Reputation: 832
I have a template that is reused to display rows with different data. The template also contains a $scope
function that is relevant to that row.
<script id="wineRowTemplateT" type="text/html" style="display: none;">
<div class="row tasting" style="margin-bottom: 15px;">
<div class="col col-10">
<div class="rating" style="display: block; width: 60px; height: 60px; text-align: center; line-height: 60px; font-weight: 700; border: thin solid #ccc; border-radius: 50%; font-size: 1.2em;">{tasting_points}p</div>
</div>
<div class="col col-90">
<div class="row info">
<div class="col col-70">
<h3 style="font-weight: 300; border-bottom: thin solid #000; display: inline-block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
<span ng-click="smGoto('http://dev.thetastingbook.com/p/{house_url}', 'external')" style="font-weight: 600;">{house_name}</span>
<span ng-click="smGoto('http://dev.thetastingbook.com/wine/{house_url}/{wine_url}', 'external')">{wine_name}</span> {wine_vintage}
</h3>
</div>
<div class="col col-30">
<h4 ng-click="showTastingAdjectivesModal($event)" data-tasting-id="{tasting_id}" data-wine-id="{wine_id}" style="font-weight: 300; text-transform: uppercase; text-decoration: underline;">Show tasting note</h4>
</div>
</div>
</div>
</div>
</script>
The function in question is the showTastingAdjectivesModal()
In my test case I have six rows being created from the template. When I try to tap Show Tasting Note on one of the rows, it fires it six times. The tastingId and wineId are from the correct row, just that it all gets fired multiple (six) times and I can't figure out what is causing it.
This is my showTastingAdjectivesModal() function:
$scope.showTastingAdjectivesModal = function (cEvent) {
console.log("showNoteModal called");
var $this = $(cEvent.toElement);
var tastingId = $this.data("tastingId");
var wineId = $this.data("wineId");
Tasting.getTastedWineAdjectives(tastingId, wineId)
.then(function(adjectives){
console.log("Got adjectives", JSON.stringify(adjectives));
adjectives.forEach(function(adj){
var type = adj.type;
if(type == "drink")
type = "conclusion";
$(".tasting-adjective-row[data-type='"+type+"']").find(".adjectives").append(adj.name + ", ");
});
$scope.noteModal.show();
});
};
The console.log
I have there is printed 6 times for every tap I make on it.
On a side note this code is running using Cordova with Ionic/AngularJS on an iOS device.
Could anyone tell me what I could be doing wrong?
Here is the usage of the template:
var res = obj.res;
var stats = obj.stats;
section = {abbr: "", proper: ""};
tastingDate = moment(tasting.tasting_date);
if (tastingDate.isAfter(moment().startOf("isoweek")) || tastingDate.isSame(moment().startOf("isoweek"))) {
section.abbr = "week";
section.proper = "This Week";
} else if (tastingDate.isAfter(moment().subtract(1, "weeks").startOf("isoweek")) || tastingDate.isSame(moment().subtract(1, "weeks").startOf("isoweek"))) {
section.abbr = "lastweek";
section.proper = "Last Week";
} else {
section.abbr = tastingDate.format("W");
section.proper = "Week " + tastingDate.format("W");
}
var wineRowTemplate = $("#wineRowTemplateT").html();
wineRowTemplate = wineRowTemplate.split("{tasting_id}").join(tasting.id);
wineRowTemplate = wineRowTemplate.split("{wine_id}").join(res.id);
wineRowTemplate = wineRowTemplate.split("{tasting_points}").join(tasting.score);
wineRowTemplate = wineRowTemplate.split("{house_name}").join(res.house_name);
wineRowTemplate = wineRowTemplate.split("{house_url}").join(res.winehouse_url_name);
wineRowTemplate = wineRowTemplate.split("{wine_name}").join(res.name);
wineRowTemplate = wineRowTemplate.split("{wine_url}").join(res.wine_url_name);
wineRowTemplate = wineRowTemplate.split("{wine_vintage}").join(res.vintage);
wineRowTemplate = wineRowTemplate.split("{last_tasted}").join(tastingDate.fromNow());
wineRowTemplate = wineRowTemplate.split("{overall_total}").join(stats.total);
wineRowTemplate = wineRowTemplate.split("{overall_average}").join(stats.average);
wineRowTemplate = wineRowTemplate.split("{overall_best}").join(stats.highest);
wineRowTemplate = wineRowTemplate.split("{overall_lowest}").join(stats.lowest);
wineRowTemplate = wineRowTemplate.split("{tb_point}").join(parseInt(res.tb_points, 10).toFixed(2));
wineRowTemplate = wineRowTemplate.split("{wine_note}").join(tasting.note);
if (!$sections.find(".section[data-section='" + section.abbr + "']").length) {
var sectionTemplate = $("#sectionTemplate").html();
sectionTemplate = sectionTemplate.split("{section_name_abbr}").join(section.abbr);
sectionTemplate = sectionTemplate.split("{section_name_proper}").join(section.proper);
$sections.append(sectionTemplate);
}
console.log("[TASTING] Inserting data to view for wine ID", tasting.wine_id);
$compile($sections.find(".section[data-section='" + section.abbr + "'] .tastings").prepend(wineRowTemplate))($scope);
Update: I noticed that if e.g. I click the first rows ng-click in the DOM, the function is only fired once, but if I click e.g. the second in the DOM, the function is fired twice. So for some reason the binding for each consecutive row increments the binding to that rows ng-click. I checked over my html structure to be certain it isn't some missing/unnecessary closing tags but this wasn't the case.
Upvotes: 0
Views: 2568
Reputation: 832
I found the issue and it was where you would least expect it. The issue landed to how I used the $compile
$compile($sections.find(".section[data-section='" + section.abbr + "'] .tastings").prepend(wineRowTemplate))($scope);
Having it wrapped around the $section (which is a parent of the rows), added an extra click listener to each consecutive row. By placing it around the prepended wineRowTemplate fixed the issue
$sections.find(".section[data-section='" + section.abbr + "'] .tastings").prepend($compile(wineRowTemplate)($scope));
Upvotes: 2