Is ajax running more than once in modal? - javascript

I am developing a feature that needs the Ajax request. First I open a modal by clicking a button that has the class '.open-email-modal'. And after that, it opens a modal where it has 2 fields to enter values for a register, and below it has a table. When opening the modal the first time, everything happens normally, the register with the call of the request Ajax goes through a controller and returns in response to the value registered with its respective token. Below are the codes I developed. (I'm using Laravel).
This is the modal code.
<div class="col-md-4">
<div class="modal fade" id="emailModal" tabindex="-1" role="dialog" aria-labelledby="modal-form" aria-hidden="true">
<div class="modal-dialog modal- modal-dialog-centered modal-lg" role="document">
<div class="modal-content">
<div class="modal-body p-0">
<div class="card bg-secondary shadow border-0">
<div class="card-header bg-transparent pb-4">
<div class="text-muted text-center mt-2 mb-3 text-uppercase"><h1>Adicionar Email</h1></div>
<div class="text-center text-muted mb-4">
<small> Preencha os campos dos emails </small>
</div>
</div>
<div class="card-body px-lg-5 py-lg-5">
<form id="emailModalProspect" method="post" action="{{ route('prospectEmails.store') }}">
#csrf
{{ method_field('post') }}
<input hidden name="prospect_id" id="prospect_id_email" type="text">
<div class="form-group mb-3">
<label class="form-control-label" for="prospect-email-name">{{ __('Nome') }}</label>
<div class="input-group input-group-alternative">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-user"></i></span>
</div>
<input class="form-control" id="prospect-email-name" name="name" placeholder="Digite o nome do proprietário do email" type="text" required>
</div>
</div>
<div class="form-group mb-3">
<label class="form-control-label" for="prospect-email-email">{{ __('Email') }}</label>
<div class="input-group input-group-alternative">
<div class="input-group-prepend">
<span class="input-group-text"><i class="ni ni-email-83"></i></span>
</div>
<input class="form-control" id="prospect-email-email" name="email" placeholder="Digite o email da empresa/cliente" type="email">
</div>
</div>
<div class="text-center">
<button type="submit" id="save-email" class="btn btn-primary my-4 store-email text-uppercase">Cadastrar email</button>
</div>
</form>
<div class="table-responsive ">
<table class="table align-items-center table-flush tablesorter-dropbox text-center" id="prospect-email-table">
<thead class="thead-light text-center" >
<tr class="text-center">
<th scope="col" class="text-center col-sm-2"><b>{{ __('Nome') }}</b></th>
<th scope="col" class="text-center col-sm-2"><b>{{ __('Email') }}</b></th>
<th scope="col" class="text-center col-sm-2"><b>{{ __('Opção') }}</b></th>
</tr>
</thead>
<tbody class="text-center" id="received-emails">
</tbody>
</table>
</div>
<div class="text-center">
<button type="button" class="btn btn-default my-4 text-uppercase" data-dismiss="modal">Fechar</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
This is the code in JQuery where it calls the Ajax request.
$('.open-email-modal').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
let p = JSON.parse($(this).attr('data-entity'));
let modal = $('#emailModal');
let form = $('#emailModalProspect');
$('#prospect_id_email').val(p.id).change();
$('.store-email').on('click', function(b){
b.stopPropagation();
b.preventDefault();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
let url = '{{route("prospectEmails.store")}}';
$.ajax({
url: url,
type: "POST",
data : form.serialize(),
async: false,
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
dataType: "json",
success:function(response) {
console.log(response);
showEmails(p.id);
}
});
});
if(p.id){
showEmails(p.id);
}
modal.modal({show : true});
});
This is my controller code.
public function store(Request $request){
ProspectEmails::create(array_merge($request->all(), ['company_id' => Auth::User()->company_id], ['prospect_id'=>$request->prospect_id], ['tag'=>false]));
return Response()->json($request);
}
The problem is this, as soon as I open for the first time and register, everything works normally. But when I close the modal and open again and register, it is returned that register that I made 2x without any token. Close the modal again and open again and register, and return that register 3x, without any token again. showEmails is a function that shows the registration in the table normally and also shows the repeated values every time that registration. Even the database shows the repeated values, so I have confirmation that the main error is either in my modal or in the Ajax request with the POST method. Can someone give me a hand?

You are registering click each time you open the modal:
$('.store-email').on('click', ...
The first time you open it, you register a listener.
The second time you open it, you register a listener, and now you have 2, and so on.
Since you don't reload the page, the listeners do not go away. You should be removing your event listener when the modal closes or checking to see if you have added it already and not adding it again:
https://api.jquery.com/off/
An easy way to do it would be to call the off method right before registering the listener, guaranteeing you only have 1 listener attached:
let modal = $('#emailModal');
let form = $('#emailModalProspect');
$('#prospect_id_email').val(p.id).change();
// ADDED LINE
$('.store-email').off('click');
$('.store-email').on('click', function(b){

Related

How do I add new row of data with javascript?

I'm creating add file function for my user, in this function, user have to insert their file name, choose their file then click on the Add Document button.
once user have add the document it will display back the user document under the add document button. User can add more as many as document they want.
I have trouble in adding the data. The file keep getting missing when user try to attach new file.
I want to display all file list of the user before the submitting it.
first add document
then user wants to add another document, the first document get replaced
second document
how do I make it not to overwrite the older document when user add more document ?
<div class="col-md-12 mb-3">
<textarea class="form-control" id="name" ></textarea>
</div>
<div class="col-md-12 mb-3">
<button type="button" class="btn btn-success w-100 choseDoc">Select document</button>
<input type="file" id="file" hidden>
</div>
<div class="col-md-12 mb-3">
<button type="button" class="btn btn-info w-100" onclick="myFunction()">Add Document</button>
</div>
<div>
<p id = "demo"></p>
</div>
<script>
function myFunction() {
let filename= $('#name').val();
let doc = $('#file').val();
let fileData = '';
fileData += `<div class="tab-content col-12 mt-4" id="myTabContent-2">
<div class="tab-pane fade show active" id="addCustodian" role="tabpanel" aria-labelledby="addCustodian-tab">
<div class="col-md-12">
<ul class="perfomer-lists m-0 p-0" id="">
<li class="d-flex mb-4 align-items-center">
<img class="avatar-20 rounded ml-2" src="assets\avatar.png" style="width: 50px;">
<div class="media-support-info ml-3">
<a class="font-size-12 font-weight-600"><b>${filename}</b></a>
<p class="mb-0 font-size-12"> ${doc}</p>
</div>
</li>
</ul>
</div>
</div>
</div> `;
document.getElementById("demo").innerHTML = fileData;
Besides the fact that your approach brings some pitifals in performance you have a little logical mistake
<div class="col-md-12 mb-3">
<textarea class="form-control" id="name" ></textarea>
</div>
<div class="col-md-12 mb-3">
<button type="button" class="btn btn-success w-100 choseDoc">Select document</button>
<input type="file" id="file" hidden>
</div>
<div class="col-md-12 mb-3">
<button type="button" class="btn btn-info w-100" onclick="myFunction()">Add Document</button>
</div>
<div>
<p id = "demo"></p>
</div>
<script>
let fileData = ''; // <--- must be declared outside your function to keep the state
function myFunction() {
let filename= $('#name').val();
let doc = $('#file').val();
fileData += `<div class="tab-content col-12 mt-4" id="myTabContent-2">
<div class="tab-pane fade show active" id="addCustodian" role="tabpanel" aria-labelledby="addCustodian-tab">
<div class="col-md-12">
<ul class="perfomer-lists m-0 p-0" id="">
<li class="d-flex mb-4 align-items-center">
<img class="avatar-20 rounded ml-2" src="assets\avatar.png" style="width: 50px;">
<div class="media-support-info ml-3">
<a class="font-size-12 font-weight-600"><b>${filename}</b></a>
<p class="mb-0 font-size-12"> ${doc}</p>
</div>
</li>
</ul>
</div>
</div>
</div> `;
document.getElementById("demo").innerHTML = fileData;

Opening show page in a modal with updating url in address bar using HTML & JS

I want to get id of button click in the address bar to take relivent data from database like instagram did.
I want to get id from the adress bar using php to find the specific data from database according to the id of selected reference.
Note
The image below is the credit of #designer from post Stackoverflow Question.
My code snipest is:
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet"/>
<a class="btn btn-primary btnModal" data-target ="#scrapModal" href="washingPlan.php#scrapModal?id=' . $row['id'] . '" data-toggle="modal" >Service Include</a>
<div class="modal fade bd-example-modal-lg" id="scrapModal" tabindex="-1" role="dialog" aria-labelledby="scrapModal" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<!-- DataTales Example -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">WASHING PLAN SERVICES</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<input type="text" name="id" id="id" />
<thead>
<tr>
<th>S.No.</th>
<th>Washing plan Services</th>
<th>Action</th>
</tr>
</thead>
<tfoot>
<tr>
<th>S.No.</th>
<th>Washing plan Services</th>
<th>Action</th>
</tr>
</tfoot>
<tbody>
<tr>
<th>test</th>
<th>test1</th>
<th>test2</th>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<form action="" method="post">
<div class="col-lg-8 m-4">
<label class="ml-1">Plans Include</label><br>
<input type="text" id="plans" name="plans" placeholder="" class="col-12" required>
</div>
<div class="row m-5">
<input type="submit" value="Reset" class="btn" style="background-color: #FF9933;letter-spacing: 0.6px;border-radius: 2px;color: #FFF;">
<input type="submit" class="btn" name="includeService" value="Add Value" style="background-color: #0891FF;;letter-spacing: 0.6px;border-radius: 2px;color: #FFF; display: inline-block;vertical-align: middle;">
</div>
</form>
</div>
</div>
</div>
Its address didn't not changed when I add data-target=modal. Is there any technique to make a modal like this?
Thank you in advance
I'd say you're looking for the History API, which allows you to manipulate the browser history (including the URL bar) using JS.
history.pushState() allows you to 'add' a page to the history stack, which will change the URL to whatever you specify.
If you listen to the window.onpopstate event, you can detect when the user navigates history using the browser controls (such as the back button), interrupt it and handle it yourself, all without reloading the page!
That should be plenty to get you started, it's a very useful API to take advantage of.

Display submitted form data in Java Spring MVC bootstrap modal

What I am trying to do: Display a value entered into a form in the modal that is shown by submitting the form.
What I tried first: To simply reference the "id" element in the modal. Realized this probably would not work because the modal is generated during page load and before the form has any values. So the value will be empty.
What I am currently trying: To return the form value after submission from my controller. Use boostrap Table('load', data) to load the table after form return and display in the modal.
I am very new to Java and feel like I may be making this a lot more complicated than it needs to be. Here is the current code:
If any additional code snippets needed, let me know...
javascript - I know I am making it into submit.done because the table is displaying, just no data.
$table = $("#notesTable").bootstrapTable({
data: []
});
$("#notesTable").hide();
$("#btnSubmit").click(function() {
var dataString = $("#extractForm").serialize();
var submit = $.ajax({
url: "${pageContext.request.contextPath}/doc/validateAuditId",
type: "POST",
cache: false,
data: dataString
});
submit.done(function(data) {
if (data.length && data.length > 0) {
$("#notesTable").show();
$("#notesTable").bootstrapTable('load', data);
$("#dlgUpload").modal('show');
}else{
$("#notesTable").hide();
$("#dlgUpload").modal('show');
}
});
Return from controller
Modal:
<html>
<body>
<div id="dlgUpload" class="modal fade" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="noteTitle">Upload File</h4>
</div>
<div class="modal-body">
<div class="tabs-div">
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active">Upload Document</li>
<li role="presentation">Select Doc Type</li>
<li role="presentation">Perceptive Content</li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane fade in active" id="tabUploadDoc">
<br>
<form:form method="POST" action="${pageContext.request.contextPath}/doc/uploadFile" enctype="multipart/form-data">
<div class="row">
<div class="col-xs-3 form-group">
<form:label path="fileName">Select a file to upload:</form:label>
</div>
<div class="col-xs-2 form-group">
<input type="file" name="fileName" />
</div>
</div>
<table id="notesTable" data-classes="table table-striped table-no-bordered" data-undefined-text="" data-toggle="table">
<thead>
<tr>
<th data-field="retAuditId" data-visible="true" data-align="left" data-sortable="false">Audit ID</th>
</tr>
</th>
Output: Nada
Need to return a list from the controller. Was returning a String.

javascript scrollIntoView function does not work inside my global event listener

I'm using scrollIntoView to scroll after creating form dynamically with javascript. Using the same way on chrome console works fine but when used inside my event method it does nothing. can you help me why?
html form to copy
<div id="comment_form_template">
<div class="row shadow mx-1 my-2 border rounded border-secondary bg-light">
<div class="container-fluid">
<div class="row p-1 bg-info rounded-top" id="comment_form_title_color">
<h6 class="my-auto text-white font-weight-bold "><small>comment</small></h6>
</div>
<div class="row">
<form action="#" method="POST" class="col-12 mt-1 px-1">
{% csrf_token %}
{{ comment_form.comment | append_attr:"class:col-12" | attr:"style:font-size:12px; height:85px; resize:none;" }}
<button type="submit" class="mb-1 float-right btn btn-info btn-sm px-1 py-0">
<small>submit comment</small>
</button>
</form>
</div>
</div>
</div>
</div>
javascript
window.onload = () => {
var form_template = document.getElementById('comment_form_template');
var test = form_template.cloneNode(true);
test_form = test.querySelector("#comment_form_title_color")
test_form.setAttribute("class", "row p-1 bg-warning rounded-top");
test_form.firstElementChild.setAttribute("class", "my-auto text-dark font-weight-bold ")
document.addEventListener("click", (e) => {
var t = e.target.id.split("_")[1]
if (e.target.id.split("_")[0] === "node" ) {
var target_div = document.getElementById(`hiddenInput_${t}`)
var target_div_isForm = target_div.getAttribute("data-isForm")
if (target_div_isForm === "False"){
target_div.innerHTML = test.innerHTML
target_div.setAttribute("data-isForm", "True")
} else if (target_div_isForm === "True"){
target_div.innerHTML = ""
target_div.setAttribute("data-isForm", "False")
}
}
e.target.scrollIntoView()
// target_div.scrollIntoView() doesn't work as well
})
};
element which i want my screen to move
<div id="hiddenInput_{{node.pk}}" data-isForm="False"></div>
element that i click to make a form
<div class="row d-inline-flex float-right mr-1">
<small class="ml-2 text-dark"><strong>subComment</strong></small>
</div>
by the way the form creates fine but the problem is that after creating the form screen scrolls up to top of the page

Using AngularJS to close Bootstrap Modal window

I'm fairly new to AngularJS, so forgive me if this is a simple question;
I have an AngularJS (v 1.6) app with a user login via a bootstrap modal window.
After the user successfully logs in, I want the modal window to be closed by Angular;
The User login is via a POST call to PHP which queries the database - this all works as expected, but i need the modal window to close if the login was successful. (The PHP responds with a JSON object)
In particular, im looking to replace this code in the Angular controller:
//window.location.href = '/IDD';
with a command to close the modal window.
HTML Code:
<nav class="navbar fixed-top navbar-dark bg-dark">
<a class="navbar-brand" href="">JDCSupport</a>
<div class="nav navbar-nav" style="flex-direction: row;">
<p class="text-center">{{usrName}}</p>
<div data-ng-show="btnLogin">
<button class="btn btn-success btn-sm pull-xs-right"
style="padding: 10px;" data-toggle="modal"
data-target="#loginModal">
Login
</button>
</div>
<div data-ng-show="btnLogout">
<button class="btn btn-warning btn-sm pull-xs-right"
style="padding: 10px; margin-right: 10px;"
type="button">
Logout
</button>
</div>
<div data-ng-show="btnMenu">
<button class="navbar-toggler pull-xs-right" style="padding: 10px;" id="navbarSideButton" type="button">☰</button>
</div>
</div>
<ul class="navbar-side" id="navbarSide">
<li class="navbar-side-item">
Home
</li>
<li class="navbar-side-item">
Staff Roster
</li>
<li class="navbar-side-item">
Photos
</li>
<li class="navbar-side-item">
Messages
</li>
</ul>
<div class="overlay"></div>
</nav>
<div id="loginModal" class="modal fade text-center">
<div class="modal-dialog">
<div class="col-lg-8 col-sm-8 col-12 main-section">
<div class="modal-content">
<div class="col-lg-12 col-sm-12 col-12 user-img">
<img src="images/man.png" alt="">
</div>
<div class="col-lg-12 col-sm-12 col-12 user-name">
<h1>User Login</h1>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="col-lg-12 col-sm-12 col-12 form-input">
<form ng-submit="loginForm()" name="loginform" method="POST">
<div class="form-group">
<input type="email" class="form-control" placeholder="Email" data-ng-model="user.username" name="username" required>
</div>
<div class="form-group">
<input type="password" class="form-control" placeholder="Password" data-ng-model="user.password" name="password" required>
</div>
<button type="submit" class="btn btn-success">Login</button>
<div class="alert alert-danger" data-ng-show="errorMsg">{{error}}</div>
</form>
</div>
<div class="col-lg-12 col-sm-12 col-12 link-part">
Forgot Password?
</div>
</div>
</div>
</div>
</div>
And my Angular Controller:
app.controller ("logController", function ($scope, $http) {
$scope.btnLogin = true;
$scope.btnLogout = false;
$scope.btnMenu = false;
$scope.errorMsg = false;
$scope.loginForm = function() {
var ans="";
var encodedString = 'username=' +
encodeURIComponent(this.user.username) +
'&password=' +
encodeURIComponent(this.user.password);
$http({
method : 'POST',
url : 'php/login.php',
data : encodedString,
headers : {'Content-type': 'application/x-www-form-urlencoded'}
}).then(function (response) {
console.log(response);
ans = response.data;
if (ans.message == 'correct' ) {
$scope.btnLogin = false;
$scope.btnLogout = true;
$scope.btnMenu = true;
//window.location.href = '/IDD';
} else {
$scope.errorMsg = true;
$scope.error = ans.error;
}
},
function (response) {
//error handling
});
};
});
use the following on login successful
$('#loginModal').modal('hide');
You can achieve that with $('loginModal').modal('hide'); or $('loginModal').modal('toggle');

Categories

Resources