angular ng-click event not firing - javascript

I have a function that adds certain html to my page when called :
function htmlAppend(i)
{
dynamicHtml = dynamicHtml + '<div id="list_item_wrapper">' +
'<div class="list_item_template" id="list_image_wrapper">' +
'<img class="list_image_style" ' +
'src=" ' + jsonData.cars[i].ImgURL + ' "/>' +
'</div>' +
'<div class="list_item_template white_font car_details_wrapper">' +
jsonData.cars[i].CarName+ '<br>' +
jsonData.cars[i].Brand + '<br>' +
jsonData.cars[i].Model + '<br>' +
jsonData.cars[i].FuelType + '<br>' +
'<span style="font-size:40px;">' +
'₹ ' + jsonData.cars[i].Price +
'</span> <br> ' +
jsonData.cars[i].Experience +
'<input type="button" id="buy_now_btn" class="button1" ng-click="alert("hi")">Buy</button>' +
'</div>' +
'</div>'
}
Problem : Now this html is displayed correctly in my page but for some reason when button is clicked ng-click event doesn't fire , when i replaced it with onClick then onClick fires . i am unable to understand why ng-click is not firing , can somebody help ?
Additional Info : htmlAppend is a private function of a service that is called from the controller upon some user input.

No, you can't just write alert on your ng-click. When you write alert("hi") on your ng-click directive, it automatically goes and look for a method in your controller that is named $scope.alert(). That is why onClick works, because it is just plain old JavaScript, where as ng-click involves scope binding.
In your controller, write this:
$scope.alert=function(string){
alert(string);
};
and you are good to go. Here is the working plnkr.
Edit: did not read carefully that you are dynamically binding it. Updated plnkr.
For this case you will need to compile it:
var $el = $('<button ng-click=' + 'alert("hello")' + '>I am a button</button>');
$compile($el)($scope).appendTo('#testing');
where #testing can be any DOM selector you want.
Still the point is to tell you you can't just write alert in ng-click directive.
Added bonus: do not write DOM manipulating logic inside the controller. You may want to use a directive instead.

Related

How do i use onclick() method properly when passing some variable arguements i.e the arguements in this case is an ID of a Mongoose Object Document?

So I'm dynamically appending rows to a table on front-end, based on the array I get from a node.js API I wrote. The array indicates students. For each row I append and display Name, Class, Roll_No and a dynamic button whose color changes depending on the value I get from that specific student. Now for that button I use the following tag:
$('#users').append("<tr><td>" + (i + 1) + "</td><td>" + val.first_name + " " + val.last_name + "</td><td>" + val.roll_no + "</td><td>" + val.class + "</td><td><button id='tempButton' class='btn btn-danger' onclick='add_remove_student(" + val._id + ", " + val.is_linked + ")'>DELETE</button></td></tr>");
val indicates the current element of the students array, which is a mongoose object. Now I get an error whenever I click the appended button and the add_remove_student() method is not called. The error says:
uncaught SyntaxError: Invalid or unexpected token
val._id is a Mongoose ID of that particular Mongoose object and val.is_linked is a boolean value.
The onclick() in the button tag worked before I switched to node.js
I've scratched my head so many times as to what I'm doing wrong. Any help would be greatly appreciated!
The short answer: don't use onclick, or any other of the onX inline event attributes. They are outdated, lead to spaghetti code and don't follow the separation of concerns principle.
A much better way to achieve this would be to just add the relevant meta data to the element as data attributes. Then, using a single delegated event handler, you can read that metadata from the element which was clicked. Try this:
let i = 0;
let val = {
_id: "5e4780d3cfbe57182499506a",
role: ["STUDENT"],
is_active: true,
linked_students: [],
first_name: "test_fname",
last_name: "test_lname",
email: "t1#t.com",
roll_no: "537",
class: 7,
description: "im a test user mate!",
created_at: "2020-02-15T05:25:39.077Z",
updatedAt: "2020-02-15T05:25:39.077Z",
v: 0,
is_linked: true
}
$('button').on('click', function() {
$('#users').append(`<tr><td>${(++i)}</td><td>${val.first_name} ${val.last_name}</td><td>${val.roll_no}</td><td>${val.class}</td><td><button class="delete btn btn-danger" data-id="${val._id}" data-linked="${val.is_linked}">DELETE</button></td></tr>`);
});
$('#users').on('click', '.delete', function() {
let $btn = $(this);
let id = $btn.data('id');
let isLinked = $btn.data('linked');
console.log(id, isLinked);
// do something with the above data...
$(this).closest('tr').remove();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Append</button>
<table id="users"></table>
As a side note, don't use id attributes in content which will be dynamically repeated. id need to be unique in the DOM. Use class attributes instead.
If, for whatever reason, you absolutely had to use an inline event attribute you need to fix your quotes so that they match, and you also need to escape the quotes you use in the onclick value so they don't interfere with the outer string:
$('#users').append('<tr><td>' + (i + 1) + '</td><td>' + val.first_name + ' ' + val.last_name + '</td><td>' + val.roll_no + '</td><td>' + val.class + '</td><td><button id="tempButton" class="btn btn-danger" onclick="add_remove_student(\"' + val._id + '\", \"' + val.is_linked + '\")">DELETE</button></td></tr>');
Okay so I've wrecked my brain for 24 hrs to solve this and after understanding how escape quotes characters work i've finally solved it with the following code:
$('#users').append(`<tr><td>` + (i + 1) + `</td><td>` + val.first_name + ` ` + val.last_name + `</td><td>` + val.roll_no + `</td><td>` + val.class + `</td><td><button id="tempButton" class="btn btn-danger" onclick='add_remove_student(\"` + val._id + `\",\"` + val.is_linked + `\")'>DELETE</button></td><tr>`);
Thank You ^^
This is the issue of mixing of quotes please re verify the quotes on the function calling in jquery. Plus please made an id of the element dynamic.

When I .load a HTML template, JSON elements don't populate but they work fine as static HTML.

I don't think this is a broken code question as much as it is a question about understanding JS.
I have HTML templates that I load when an element is clicked. To be clear, there is already an HTML template loaded on document.ready that has all functionality working just fine. The HTML that loads is the exact HTML that is in place when you intitially load the page, aside from some small differences(images, etc...). This all loads no problem, but for some reason my JSON elements don't load. Is this because the actual javascript I wrote that is responsible for loading the JSON is within the document.ready wrap?
To be clear, the HTML is EXACTLY the same, aside from text and img src's. I have provided the JS though since that may be the issue.
Just looking for some guidance on why this may be occurring since I also have a few other JS/jquery strings of code that also don't work on template load(like hiding elements with .hide that work on document.ready no problem, but once the template loads, the elements aren't hiding).
This all sits in $(document).ready
var trinketJSON;
$.getJSON("js/trinket.json", function (data) {
trinketJSON = data;
// TRINKET SELECTION TABLE
$.each(trinketJSON, function (i, item) {
$("<div>")
.html(
'<div class="trinket-tile"><div class="trinket-img" style=\'background-image: url("' +
trinketJSON[i].RarityBG +
'");\'><img src="' +
trinketJSON[i].TrinketIMG +
'" class="trinket-tile-img"></div><div class="trinket-effects"><ul><li class="trinket-effect">' +
trinketJSON[i].EffectOne +
'</li><li class="trinket-effect">' +
trinketJSON[i].EffectTwo +
'</li><li class="trinket-effect">' +
trinketJSON[i].EffectThree +
'</li><li class="trinket-effect">' +
trinketJSON[i].EffectFour +
'</li><li class="trinket-effect">' +
trinketJSON[i].EffectFive +
'</li><li class="trinket-effect">' +
trinketJSON[i].EffectSix +
'</li></ul></div><div class="trinket-info"><ul><li class="trinket-name">' +
trinketJSON[i].TrinketName +
'</li><li class="trinket-rarity">' +
trinketJSON[i].Rarity +
'</li><li class="trinket-class">' +
trinketJSON[i].Class +
'</li><li class="trinket-set"></ul></div></div>'
)
.appendTo(".trinket-select");
});

Put a Modal inside Javascript

I'm making a Carnival calendar for my city.
I'm using this as a basic calendar engine: https://github.com/jlord/sheetsee-calendar
For a basic Modal i'm using this: https://github.com/FinelySliced/leanModal.js
I want to be able to click on the event and put it to show some information about it: name, time and place.
var eventElement = $('<div class="event"><a class="' +
event.location + '" href="#informa" rel="leanModal" >' +
event.name + "#" + event.tickets +
'</a></div> <div id="informa"> <p>' +
event.name + '</p></div>')
I made a test modal in the index.html and it worked, but it is not working when i try to do this.
You have created an element, but haven't added it to the DOM of the page.
try something like
$('body').append(eventElement);
as the next line.

Can't pass js value "pageUid" in f:link.page viewhelper

I get some values from js and formatting page. I used fluid viewhelper for create link. My js look like
function buildEstablishments(title, page) {
...
$('#myid').append(
'<div class="col-md-6 col-sm-6 col-xs-6">' +
'<f:link.page pageUid="' + page + '" title="' + title + '" >More</f:link.page>' +
'</div>'
);
}
Everything works good, but I can't pass value "pageUid" in f:link.page viewhelper. Parametr ' + page + ' is exists and has a value. How can even pass values? Thanks.
You can not, in simple words all Fluid syntax works on server side and JS works on client side, that means that server side job is done long, long before it goes to the client (if you're using caching it may be months or years before client side will load it), you can use it rather like this:
In your Fluid view:
<div onclick="buildEstablishments('{someTitle}', '{f:uri.page(pageUid: somePageUid)}')">Foo Bar Baz</div>
Where of course {someTitle} and {somePageUid} are resolvable Fluid variables
so you can use it in your JS script like:
function buildEstablishments(title, href) {
// ...
$('#myid').append(
'<div class="col-md-6 col-sm-6 col-xs-6">' +
'<a href="' + href + '" title="' + title + '" >More</a>' +
'</div>'
);
}

add element containing ng-if using jquery after

I am trying to add some validation to some input using a directive. I'm using the following code to add the validation alert but the ng-if doesn't seem to be registering and the messages are constantly displayed.
if (addMessages) {
angular.element(element).after('<div><span ng-if="form.' + scope.fieldName + '.$error.maxlength">Please keep it under ' + property.length + ' characters.</span></div>' +
'<div><span ng-if="form.' + scope.fieldName + '.$error.required">This field is required</span></div>')
element.removeAttr("my-directive");
$compile(element)(scope);
}
I originally tried to do this with ngMessages but they are not currently working on mdDialogs where most of my input is contained, so I came up with this solution, but its just not working for me. Any ideas?
In your code when you execute $compile(element)(scope); it is actually compiling the element which do not contain the html you just added in the previous line. It is because element.after adds the html after the element. So you have to get a reference to the dynamic element inserted and then call $compile on it, it should work fine.
if (addMessages) {
var $htmlToInsert = $('<div><span ng-if="form.' + scope.fieldName + '.$error.maxlength">Please keep it under ' + property.length + ' characters.</span></div>' +
'<div><span ng-if="form.' + scope.fieldName + '.$error.required">This field is required</span></div>');
angular.element(element).after($htmlToInsert)
element.removeAttr("my-directive");
$compile($htmlToInsert)(scope);
}
Demo http://plnkr.co/edit/Vjt1PTGfbLa6zA0iRYSz?p=preview

Categories

Resources