How can I call javascript from template vue.js 2? - javascript

My view is like this :
...
<td #click="modalShow('modal-option', '{{ $i }}')">
...
</td>
...
#section('modal')
<option-modal id="modal-option" :id="idModal"></option-modal>
#endsection
When the view clicked, it will display modal like this :
<template>
<div class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
...
<div class="modal-body">
<a href="javascript:" class="text-danger" :id="'image-delete-' + id">
<span class="fa fa-trash"></span>
</a>
</div>
...
</div>
</div>
</div>
</template>
<script>
export default{
name: 'OptionModal',
props:['id'],
}
</script>
I display modal with vue.js 2
When I click icon trash, I want to call javascript
I have global javascript. The name is main.js
The main.js is like this :
for(let i = 0; i < 5; i++) {
$('#image-delete-'+i).click(function(){
$('input[name="image-'+i+'"]').val('');
document.getElementById("image-view-"+i).style.display = "none";
document.getElementById("image-upload-"+i).style.display = "";
$('.modal').modal('hide');
});
}
When I clicked the trash icon in modal, javascript was unsuccessful called
How can I solve this problem?

Whether the click handlers you are adding via jQuery will work depends entirely on when you add the click handlers. If you are adding the click handlers before the Vue is mounted, then your clicks will never fire.
This won't work
for(let i = 0; i < 5; i++) {
$('#image-delete-'+i).click(function(){
...
});
}
new Vue(...)
Here is an example.
If you add your handlers in mounted, then you can get it to work.
This should work
new Vue({
el:"#app",
data:{
},
mounted(){
for(let i = 0; i < 5; i++) {
$('#image-delete-'+i).click(function(){
...
});
}
}
})
Example.
Finally, you could add your handlers in this fashion and it wouldn't matter when you added them.
for(let i = 0; i < 5; i++) {
$(document).on("click", `#image-delete-${i}`, function(){
...
});
}
But, I'm not sure this is what is happening because you give so little code. Of course the ideal case would be to let Vue define the handlers.

Related

AJAX incorrectly GETs and POSTs multiple data

I am working on a feature of my webapp that allows a user to add a place to a list. The current path is to open a modal which shows the user's lists and allows them to choose which list to add the data to.
The problem I have is two fold:
For some reason when the user click's a list it tries to send the data multiple times depending on how many lists there are (eg. if there are 2 lists it tries to send the data to the chosen list twice.) This is causing all sorts of headaches at my database.
The modal doesn't seem to reset or something meaning every time I reopen the modal 2 more lists are added meaning there are all these duplicates (example).
I have tried adding and removing event handlers etc. but I can't seem to debug the issue myself. Thank you in advance for any support you can offer.
Here is the JS function
const addToListModal = function(venueName) {
$('#userlist-modal').modal('show');
$.ajax({
type: 'GET',
url: '/api/userlist/',
data: {
'username': userName
},
success: function(data) {
data.forEach(item => {
var listName = item.list_name;
var listId = item.id;
var listItem = $("#userListsModal").append(
`<li class="userlistModal" id="${listName}" data-name="${listName}" data-pk="${listId}">
${listName}
</li>`)
$(listItem).on('click', function(e) {
if (e.target && e.target.matches("li.userlistModal")) {
var listname = e.target.getAttribute('data-name');
var listId = e.target.getAttribute('data-pk');
addVenueToList(listId, venueName);
e.preventDefault();
}
})
})
}
});
};
AJAX Post:
const addVenueToList = function(listId, venue) {
$.ajax({
type: "POST",
url: '/api/uservenue/',
dataType: 'json',
data: {
csrfmiddlewaretoken: document.querySelector('input[name="csrfmiddlewaretoken"]').value,
'user_list': listId,
'venue': venue
},
success: function(data) {
console.log('User added: ' + data)
},
});
}
And here is the pertinent HTML
<div class="modal" id="userlist-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content rounded-0">
<div class="modal-header">
<h5 class="modal-title" id="ModalLabel"></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div id="lists-column" class="mt-1 ml-2 mb-1 col-2" style="height: 367px;">
<ul id="userListsModal" class="list-group list-group-flush" style="width: 250px">
{% csrf_token %}
{{ form.as_p }}
</ul>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
$(listItem).on('click', function(e) { …
listItem is not what you think it is here.
You did
var listItem = $("#userListsModal").append(`<li class="userlistModal" …
before - but that does not return a reference to the newly appended item, it returns the jQuery object you started with (that is necessary, for method chaining to work).
So what you are doing here, is adding a click handler for #userListsModal. And since this happens in a loop over your list items, you are adding this same click handler twice (here in this situation), resp. as many times, as you have list items.
Your check
if (e.target && e.target.matches("li.userlistModal")) {
inside the callback function still works - because when you click on any of the list items, the event bubbles up the DOM tree. You are handling it when it reaches #userListsModal, but the event target is still the list item you clicked on.
You need to either add these event handlers to the individual new list items you just appended, or – probably better in a case like this – use event delegation, set up one handler for this, outside of the loop that creates the list items.
Try using jQuery's one() method: one
So, instead: $(listItem).on('click', function(e) {...})
Do this: $(listItem).one('click', function(e) {...})
I think the problem here is that the list (of lists) is not cleared every time you open the modal dialog. So every time the same items are appended and new 'click' event handlers are added. Try to call jQuery empty() method before running AJAX '/api/userlist' (it will remove all event handlers as well)
const addToListModal = function(venueName) {
$("#userListsModal").empty();
$('#userlist-modal').modal('show');
$.ajax({
// ...

Javascript Issue with aria-hidden popup

I have this ajax code that gets a res.json(event) from the server and then creates an object based on the value received.
Here is part of that code:
html += `<div class="card-header" id="headingOne-${i}">` +
`<div class="event-time"><time class="published" datetime="2017-03-24T18:18">${data[i].events.targetReminder} | ${data[i].events.targetAmPM}</time><div class="more"> <svg class="olymp-three-dots-icon"><use xlink:href="svg-icons/sprites/icons.svg#olymp-three-dots-icon"></use> </svg><ul class="more-dropdown"><li>Mark as Completed</li> <li>Delete Event </li></ul></div></div>` +
`<h5 class="mb-0 title"><a href="" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne" >${data[i].events.title}<i class="fa fa-angle-down" aria-hidden="true"></i>` +
` <span class="event-status-icon" data-toggle="modal" data-target="#public-event"><svg class="olymp-calendar-icon" data-toggle="tooltip" data-placement="top" id ="uncomplet-${i}"data-original-title="UNCOMPLETED"><use xlink:href="svg-icons/sprites/icons.svg#olymp-calendar-icon"></use></svg></span></a></h5></div>` +
`<div id="collapseOne" class="collapse show" aria-labelledby="headingOne" data-parent="#headingOne-${i}"><div class="card-body" id="${data[i].events._id}" onClick="reply_click()">${data[i].events.caption}</div><div class="place inline-items"><svg class="olymp-add-a-place-icon"><use xlink:href="svg-icons/sprites/icons.svg#olymp-add-a-place-icon"></use></svg><span>${data[i].events.location}</span></div></div></div>`;
And here is the output of the code:
The aria-hidden that I'm talking about is this one
<div class="modal fade" id="public-event" tabindex="-1" role="dialog" aria-labelledby="public-event" aria-hidden="true">
What I have tried and already know it's not a proper solution is here
Code test
I created a script that change aria-hidden => true or false but I don't know how to link it with my box
<script type="text/javascript">
function reply_click()
{
document.getElementById('public-event').setAttribute('aria-hidden', 'false');
}
</script>
another failed try:
<script type="text/javascript">
function reply_click()
{
alert('this function is called')
$(`#mark-${i}`).onclick = function() {
document.getElementById('public-event').setAttribute('aria-hidden', 'false');
};
}
</script>
I also added in the HTML this function onClick="reply_click()" but nothing is happening. I only get the alert('this function is called')
Could you suggest me an idea, please?
By looking at your question and discussion on the comment section I think that you are trying to add click event on your dynamically generated div section(html part) and open the pop up modal.
We can achieve that by using $('#id' OR '.class').modal('show') in jquery.
So why don't you add a class any where inside your div section of html and bind a click function using jquery. Suppose you have added a class name showModal on the very first div after card-header like, div="card-header showModal"
$('#eventCard').on('click', '.showModal', function(){
$('#public-event').modal('show');
});
We cannot directly use $('.showModal').click...... because document structure is change after appending the html section after #eventCard which was initially was not present. Hpe this works.
could this be your problem ? you create an item dynamically with javascript, but the item you want to select, click event, is not actually created at that time. Once the item you want to export is created, you can select it and want to make the changes you want.
udpated: I added a snippet of what I meant. in order for me to select the H1 tag that occurs after I click on the button, I have to write a function that will occur after it occurs.
const button = document.querySelector(".clickme");
const container = document.querySelector(".container");
button.addEventListener("click", () => {
container.innerHTML += `
<h1 class = "change-modal"> ı cant select this</h1>
<div class="modal fade" id="public-event" tabindex="-1" role="dialog" aria-labelledby="public-event"
aria-hidden="true"> `
})
const changeModal = document.querySelector(".change-modal")
console.log(changeModal)
<button class="clickme">Click me</button>
<div class="container" style="background-color: red;">
</div>
<h1 class="change-modal">ı select this</h1>
updated2 :
for (let i = 0; i < data.length; i++) {
html += // your html
$("eventCard").append(html);
//after this, you can select the item and type the function because the items are created here.
}
Updated 3!!! : I explained how to do things with javascript without using jquery. Hopefully you know what I mean.
async getData() { // fetch operations using javascript
const data = await fetch(url); // your api url
const jsonToData = await data.json(); // here you can Request api and obtain the data
return jsonToData;
}
getData().then((data) => {
console.log(data) // ıts probably an array.
for (let data = 0; data < jsonToData.length; data++) {
// data operations, what if you want to
html += // you printed document items,
}
})
.then(() => {
//!!! IMPORTANT!!! this is where you need to perform the operation of selecting the element function. you can also write a function that can work for the code here, but I've written it one by one for now.
const clickedElement = //type whatever element you want to click on. !!
clickedElement.addEventListener("click", function() {
const elementToChange = document.getElementById(".public-event");
elementToChange.setAttribute('aria-hidden', 'false');
})
})
.catch(err => console.log(err))

jQuery single class selector not firing when target has multiple classes

I cannot figure out why my jQuery event handler does not fire in this cirucmstance. I have exhausted my research on Stack Overflow.
HTML:
<div class='pst-header-ad parenting pst-subscribe-motherhood-kit'>
<div class='pst-header-ad-wrap'>
<h3></h3>
<p></p>
</div>
</div>
JS, which does not fire as it should when user clicks element with class pst-subscribe-motherhood-kit:
var subscribeForms = [
{
formclass : "pst-subscribe-motherhood-kit",
formnumber : "151496",
formtitle : "Get Your FREE Mom Kit Now!",
formdescription : "Leave your email below and we'll send you our Mom Kit packed full of printables that will make your mom journey more fun. You'll also receive email updates from me from time to time. Enjoy your Mom Kit!!",
formredirect : "https://pintsizedtreasures.com/landing-pages/mom-bundle-offer/"
}, {
formclass : "pst-subscribe-marriage-kit",
formnumber : "151501",
formtitle : "Get Your FREE Marriage Kit Now!",
formdescription : "Where should we send your Marriage Kit? Leave your email below and you'll receive three printables: a praying for your husband printable, simple, romantic ideas printable and love notes printable. You'll also receive email updates from time to time from me. Enjoy your Marriage Kit!",
formredirect : "https://pintsizedtreasures.com/landing-pages/marriage-bundle-offer/"
}
];
for (var i = 0; i < subscribeForms.length; i++) {
jQuery("." + subscribeForms[i].formclass).click(function(e) {
e.preventDefault();
for (var j = 0; j < subscribeForms.length; j++) {
if (this.className == subscribeForms[j].formclass) {
var formnumber = subscribeForms[j].formnumber;
var formtitle = subscribeForms[j].formtitle;
var formdescription = subscribeForms[j].formdescription;
loadForm(formnumber, formtitle, formdescription);
}
}
});
}
FYI, this loop dynamically loads event handlers from an object of various subscription form data. The selector looks like this in practice:
jQuery(".pst-subscribe-motherhood-kit").click(function(e) { ... }
Research as shown me that when pst-subscribe-motherhood-kit is the element's class value alone, without any other class, jQuery fires as expected.
WORKS: <div class="pst-subscribe-motherhood-kit">Some text</div>
DOES NOT WORK: <div class="my-class pst-subscribe-motherhood-kit">Some text</div>
As always, any help is appreciated.
EDIT: added the object that is iterated through. And, YES, the DOM is loaded before this function is called. It is called in the footer.
You can use let instead of var for creating individual scope in each iteration of the for loop:
var subscribeForms = [{formclass: 'pst-header-ad-wrap'},{formclass: 'pst-header-ad-wrap-2'}];
for (let i = 0; i < subscribeForms.length; i++) {
jQuery("." + subscribeForms[i].formclass).click(function(e) {
e.preventDefault();
console.log(subscribeForms[i].formclass);
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='pst-header-ad parenting pst-subscribe-motherhood-kit'>
<div class='pst-header-ad-wrap'>
pst-header-ad-wrap
<h3></h3>
<p></p>
</div>
<div class='pst-header-ad-wrap-2'>
pst-header-ad-wrap-2
<h3></h3>
<p></p>
</div>
</div>

angular ng-src doesn't refresh an image

I am doing a functionality of selecting an image from the image list. I have a button "select" from every button and call selectImage method on button-click.
AngularApp:
app = angular.module("BlogImageApp", []);
app.controller("BlogImageController", function($http, $scope){
$scope.selectedImageId = null;
$scope.selectedImageUrl = "";
$scope.selectImage = function(image_id) {
$scope.selectedImageId = image_id;
var params = 'id='+image_id;
$http.get('/blog/image/get-url-by-id?'+params).success(function(data){
$scope.selectedImageUrl = data;
});
}
});
// registers the BlogImageApp in the view
angular.bootstrap(document, ['BlogImageApp']);
The view:
<div id="blog-images" ng-controller="BlogImageController">
<div ng-show="selectedImageId == null" style="height:50px; margin-bottom:5px;">
<div class="alert alert-info">
<span class="glyphicon glyphicon-info-sign"></span>
The image isn't selected!
</div>
</div>
<div class="blog-selected-image" ng-hide="selectedImageUrl == ''">
<b>The selected image: <span ng-bind="selectedImageUrl"></span> </b><br/>
<img ng-src="{{selectedImageUrl}}" class="img-thumbnail" style="height:200px">
</div>
...
PJAX PART GOES HERE WITH GRID AND PAGINATION
and button with ng-click="selectImage(39)" for every item
PJAX PART ENDS
And after all in javascript:
var ngRefresh = function() {
var scope = angular.element(document.body).scope();
var compile = angular.element(document.body).injector().get('$compile');
compile($(document.body).contents())(scope);
scope.$apply();
}
// PJAX
$(document.body).on('pjax:success', function(e){
ngRefresh();
});
After pjax call I have some strange behaviour. When I click a select button, selectImage method is invoked. It changes selectedIMageUrl and I can see different url in span every time I click select button. But the image (where ng-src specified) doesn't change.
Image changing worked great before pjax call though.
PS: I understand, that it would be better to do jsFiddle snippet, but I would have problem with server side.

Dynamically assign ID

I am using nodejs and expressjs.
I load a list from a database. Selecting any of the list elements bring up an overlay with to EDIT and DELETE the selected item. I can not figure out how to send the selected list item to the express route.
What I believe needs to be done: Dynamically assign an ID to the buttons on the overlay. I tried to make a jfiddle but the overlay would not work.
Any ideas? I am sliding the overlay into view with jquery.
Thank you for taking the time to read this
I have a dynamically created list, each item with the class ".recordlongpress" and I apply this Jquery functionality to it.
$(document).ready(function(){
$('.recordlongpress').bind('tap', function() {
return;
});
$('.recordlongpress').bind('taphold', function() {
$('#overlay').fadeIn('fast',function(){
$('#box').animate({'top':'100px'},500);
});
});
$('#boxclose').click(function(){
$('#box').animate({'top':'-100px'},500,function(){
$('#overlay').fadeOut('fast');
});
});
});
Which brings up my overlay which is done by a combination of CSS and this HTML
<div class="overlay" id="overlay" style="display:none;"></div>
<div class="box" id="box">
<a class="boxclose" id="boxclose"></a>
<button onclick="location.href='/scape/editcustomerform/id'">Edit Contact</button>
<button onclick="location.href='/scape/deletecustomer/ID'">Delete Contact</button>
<button>E-mail Customer</button>
<button>Call Customer</button>
<button>GPS to Address</button>
<button>Create Quote</button>
<button>Create Sales Order</button>
<button>Create Cash Sale</button>
</div>
</div>
I have tried to append the path id to the end of my route, but it just literally takes the word id. Thank you for any help
Try this:
var box = document.getElementById('box'),
buttons = box.getElementsByTagName('button');
for(var i = 0; i < buttons.length; i++){
buttons[i].id = [ 'my', 'button', 'id', i ].join('-');
}
JsFiddle
Also, you may try to "map" actions:
var box = document.getElementById('box'),
buttons = box.getElementsByTagName('button');
var map = [
'editcustomerform',
'deletecustomer',
'emailcustomer',
'callcustomer',
'gpstocustomer',
'createquote',
'createsalesorder',
'createcashsale'
];
for(var i = 0; i < buttons.length; i++){
buttons[i].id = [ 'my', 'button', 'id', i ].join('-');
buttons[i].onclick = function(){ location.href = [ '/scape', map[i], 'id' ].join('/'); }
}

Categories

Resources