bootstrap modal displays twice - javascript

I have a users table with a button that shows a modal containing info about the user.
So I will have 10 rows, each with its own button, the first time I press a button, it will display a modal (let's call this modal A) containing the info for the user and work normally.
When I click on a button for another user it will display modal A then on top it will display the correct modal (modal B) when I close this modal, modal A is no longer on screen but the backdrop will still be visible.
I'm using laravel 5.5 with bootstrap 3 here is the code for the modal load.
Javascript
$(".btn").click(function(){
var button = $(this)
var employee_id = button.data('id')
var url = "/something/else/" + employee_id;
$('.modal-container').load(url,function(result){
$('#display').modal({show:true});
});
});
HTML
<a class="btn btn-primary" data-toggle="modal" data-id="{{ $simething->id }}" href="#display" id="modal_link">Show Modal</a>
This is the complete code
<table id="table" class="table" cellspacing="0" width="100%" role="grid">
<thead>
<th>ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>Events</th>
</thead>
<tbody>
#foreach ($empleados as $empleado)
<tr>
<td>{{ $simething->id }}</td>
<td>{{ $simething->fname }}</td>
<td>{{ $simething->lname }}</td>
<td>
<a class="btn btn-primary" data-toggle="modal" data-id="{{ $simething->id }}" href="#display" id="modal_link">Show Modal</a>
<div class="modal-container"></div>
</td>
</tr>
#endforeach
</tbody>
<script>
$(document).ready(function(){
$(".btn").on('click', function(e){
var button = $(this); // Button that triggered the modal
var employee_id = button.data('id'); // Extract info from data-* attributes
var url = "/somethin/else/" + employee_id;
$('.modal-container').load(url,function(){
$('#display').modal('show');
});
});
});
</script>

You are launching the modal twice every time, which after a few clicks is probably stacking up and causing the issues you're seeing. Try changing your html to not auto launch a modal, like so:
<a class="btn btn-primary modal-btn" data-id="{{ $simething->id }}" href="#/" id="modal_link">Show Modal</a>
Also, you shouldnt use the ".btn" as the way you select the button, as many buttons on your page may have that boostrap class. I would give it a unique class that you only want to target this modal with, or an ID if its for only one button per click event. Change your javascript to this:
$(".modal-btn").click(function(){
var button = $(this)
var employee_id = button.data('id')
var url = "/something/else/" + employee_id;
$('.modal-container').load(url,function(result){
$('#display').modal({show:true});
});
});

Related

How to show a modal only once per user?

I have created a Flask application that allows different users to register and log in. For this I have implemented sessions in my code. At the fist page new users arrive at, there is a modal welcoming them to the platform. I want to be able to show this modal only once to newly registered and logged in users. Alterations of this question have been answered in Stackoverflow but I tried them all and no answer helped me out.
So here is my code:
html page:
{% extends "layout.html" %}
{% block title %}
INDEX
{% endblock %}
{% block main %}
<div id="myModal" class="modal fade" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Welcome!</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Welcome to the index page! Here you can trade to your heart's content with us by your side!<span class="badge">By Rahul jangid</span></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<!--this closes, see what ull do -->
<button type="button" class="btn btn-primary">Move On</button>
<!--Here make sure to impplement the next fuinctionality. Look at changing the color of the popover. Also add some popovers.-->
</div>
</div>
</div>
</div>
<table class="table table-striped">
<thead>
<tr>
<th style ="color:red">Symbol</th>
<th style ="color:red">Name</th>
<th style ="color:red">Stock Shares</th>
<th style ="color:red">Price</th>
<th style ="color:red">Sum</th>
</tr>
<tbody>
{% for stock in stocks %}
<tr>
<td style ="color:red">{{stock.symbol}}</td>
<td style ="color:red">{{stock.name}}</td>
<td style ="color:red">{{stock.shares}}</td>
<td style ="color:red">{{stock.price | usd}}</td>
<td style ="color:red">{{stock.total | usd}}</td>
</tr>
{% endfor %}
<tr>
<td style ="color:red">CASH</td>
<td colspan ="3"></td>
<td style ="color:red"> {{cash | usd}}</td>
</tr>
</tbody>
</thead>
<tfoot>
<td style ="color:red">Initial Cash</td>
<td colspan ="3"></td>
<td style ="color:red">{{ total_cash | usd }} </td>
</tfoot>
</table>
{% endblock %}
javascript code:
$(document).ready(function () {
// Check if user saw the modal
var key = 'hadModal',
hadModal = localStorage.getItem(key);
// Show the modal only if new user
if (!hadModal) {
$('#myModal').modal('show');
}
// If modal is displayed, store that in localStorage
$('#myModal').on('shown.bs.modal', function () {
localStorage.setItem(key, true);
})
});
The problem with this code is that the modal showed only once and never again. (P.S. I have als tried the cookie approach, which didn't work either) It showed up just for one user and not for the other newly registered one. Any help would be greatly appreciated.
I think you need something like this
$(document).ready(function () {
var users = ['email1', 'email2'] //pushes all logged users here
function checkUsers() { //call this function on every log in
// Check if user saw the modal
var key = 'hadModal',
hadModal = JSON.parse(localStorage.getItem(key));
var loggedUserEmail //
// Show the modal only if new user
if (!hadModal) {
$('#myModal').modal('show');
users.push(loggedUserEmail) // push new user in users
} else {
if (!hadModal.includes(loggedUserEmail)) { // check if logged user is new
$('#myModal').modal('show');
users.push(loggedUserEmail) // push new user in users
}
}
// If modal is displayed, store that in localStorage
$('#myModal').on('shown.bs.modal', function () {
localStorage.setItem(key, JSON.stringify(users));
})
}
});

JavaScript for each record in my view

I have a VIEW where I display a table with 15 records (15 rows) and 5 columns, but the very thing that matters is a column, "Actions". In it I have 1 button, "Preview", that when clicking, I want to open a window with a message, for tests.
However, only the first record, when clicking the "View" button, displays the message window, the other 14 records do not.
How do I make all records / lines display the message?
Follow the code below:
<table class="table table-bordered table-hover tablesorter">
<thead>
<tr>
<th class="header text-center" style="width: 100px;"> Ações </th>
</tr>
</thead>
<tbody id="tabela">
#foreach (var item in Model)
{
<tr>
<td>
#this.Hidden("IdClient").Value(item.Id)
<a id="visualizarCliente" class="btn btn-primary btn-xs btn-visualizar" data-toggle="tooltip" title="Visualizar" target="_blank"
href="#Url.Action(MVC.Painel.Clientes.Visualizar(item.Id))">
<i class="fa fa-eye"></i>
</a>
</td>
</tr>
}
</tbody>
</table>
<script type="text/javascript">
$(function () {
$("#visualizarCliente").click(function () {
var idCliente = $("#IdClient").val();
window.alert("Teste");
})
});
</script>
The problem is that you are using the id selector and it can not be repeated. Switch to any other selector, such as data-toggle = "tooltip" for example.
<script type="text/javascript">
$(function () {
$("a[data-toggle='tooltip']").click(function () {
window.alert("Teste");
})
});
</script>
The problem is ID which always be used for something UNIQUE. Try to use CLASS instead. Your function should goes something like this one example:
$(function () {
$(".btn-visualizar").click(function () {
var idCliente = $(this).parent().find("#IdClient").val();
window.alert("Teste");
})
});
In the given example the line $(this).parent().find("#IdClient").val(); specifies that this would be it's nearest element value as it should be.

How to find which button is clicked: jquery

Summary: I have a html page which consists of two add buttons and two tables. When add button is clicked, rows are appended to respective table. I have included two templates with two different parent ids into one html template. I need to write the script in such a way that when add-btn having parentid == "#a" is clicked ,append rows to table having parentid =="#a".
result.html
//i am using django web framework
<div class="reports">
{% include 'template1.html' with id="a" %}
{% include 'template2.html' with id="b" %}
</div>
Each template shares/extends a base.html template where all the common code is written
<div class="panel">
<div>
<button type="button" class="add btn btn-primary" data-toggle="tooltip" title="Add to configuration list.">
<i class="fa fa-plus"></i>
Add
</button>
</div>
<div class ="configuration-table panel-body">
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Remove</th>
<th>Layer</th>
<th>Display</th>
<th>Unit</th>
<th>Dataset</th>
<th>Ordering</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
and my jquery code is
result.js
$('.reports').on('click','#a .add, #b .add', function(e) {
//how to differentiate two tables here.
$(this).find('configuration-table table').children('tbody')
.append(
'<tr>'+
'<td class="remove-row" role="button" aria-label="Remove Region"><i class="fa fa-times" title="Remove this row." data-toggle="tooltip" data-placement="right" aria-hidden="true"></i></td>'+
'<td>'+layer_text+'</td>'+
map_elements+
'<td>'+unit_text+'</td>'+
'<td>'+dataset_text+'</td>'+
'<td class="ordering" aria-label="Re-order"><i class="fa fa-arrows" title="Re-arrange row order." data-toggle="tooltip" data-placement="right"></i></td>'+
'</tr>'
);
Issue: When i click add button, the row is appending to both the tables. and i dont want that. i want to add rows to the respective table. And i want to do that within same function.
I am looking for logic that i am missing here.
Thanks in advance
Your code is using find which looks for a child of the button. It is not a child, it is a sibling of the parent div of the button.
$(this) //button that was clicked
.parent() //div around the button
.sibling(".configuration-table") //sibling element that has the table
.find("table tbody") //the table
.append(tableRow);
Firstly as per markup, there is no parent child relation between add button and table. Though, there can be many ways of fixing this issue. Proposing 1 option below
Let us say you have both buttons with class add and a data attribute (data-id) containing id of table.
i.e. 1st button having data-id="a" and second button having data-id="b" where a and b are the ids of respective tables.
Now update your js to following
.on('click','.add', function(e) {
var table_id = $(this).data("id");
$("#"+table_id).children('tbody').append..... // your code
}

How can I show data using a modal when clicking a table row (using bootstrap)?

I'm sort of a beginner on the whole web development thing and after researching a lot I still couldn't get this done. Any help is very much appreciated. I'm using latest rails version and bootstrap to make things prettier.
I have a page with a table which contains orders from a restaurant. If you click a row I want it to show the order details in a modal window using bootstrap. I have managed to open the modal via onclick+javascript function but it looks kinda messy and I still have no clue how to load the content div of the modal with the order info. Here's the code I have for this:
HTML:
<h1>Orders</h1>
<table class="table table-striped"
<thead>
<tr>
<th>ID</th>
<th>Customer</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<% #restaurant.orders.each do |order| %>
<tr onclick="orderModal(<%= order.id %>);">
<td><%= order.id %></td>
<td><%= order.customer_id %></td>
<td><%= order.status %></td>
</tr>
<% end %>
</tbody>
</table>
<div id="orderModal" class="modal hide fade" role="dialog"
aria-labelledby="orderModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
<h3>Order</h3>
</div>
<div id="orderDetails"class="modal-body"></div>
<div id="orderItems" class="modal-body"></div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
</div>
js:
function orderModal(order_id){
$('#orderModal').modal({
keyboard: true,
backdrop: "static"
});
};
One thing you can do is get rid of all those onclick attributes and do it the right way with bootstrap. You don't need to open them manually; you can specify the trigger and even subscribe to events before the modal opens so that you can do your operations and populate data in it.
I am just going to show as a static example which you can accommodate in your real world.
On each of your <tr>'s add a data attribute for id (i.e. data-id) with the corresponding id value and specify a data-target, which is a selector you specify, so that when clicked, bootstrap will select that element as modal dialog and show it. And then you need to add another attribute data-toggle=modal to make this a trigger for modal.
<tr data-toggle="modal" data-id="1" data-target="#orderModal">
<td>1</td>
<td>24234234</td>
<td>A</td>
</tr>
<tr data-toggle="modal" data-id="2" data-target="#orderModal">
<td>2</td>
<td>24234234</td>
<td>A</td>
</tr>
<tr data-toggle="modal" data-id="3" data-target="#orderModal">
<td>3</td>
<td>24234234</td>
<td>A</td>
</tr>
And now in the javascript just set up the modal just once and event listen to its events so you can do your work.
$(function(){
$('#orderModal').modal({
keyboard: true,
backdrop: "static",
show:false,
}).on('show', function(){ //subscribe to show method
var getIdFromRow = $(event.target).closest('tr').data('id'); //get the id from tr
//make your ajax call populate items or what even you need
$(this).find('#orderDetails').html($('<b> Order Id selected: ' + getIdFromRow + '</b>'))
});
});
Demo
Do not use inline click attributes any more. Use event bindings instead with vanilla js or using jquery.
Alternative ways here:
Demo2 or Demo3
The solution from PSL will not work in Firefox. FF accepts event only as a formal parameter. So you have to find another way to identify the selected row.
My solution is something like this:
...
$('#mySelector')
.on('show.bs.modal', function(e) {
var mid;
if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1)
mid = $(e.relatedTarget).data('id');
else
mid = $(event.target).closest('tr').data('id');
...
The best practice is to ajax load the order information when click tr tag, and render the information html in $('#orderDetails') like this:
$.get('the_get_order_info_url', { order_id: the_id_var }, function(data){
$('#orderDetails').html(data);
}, 'script')
Alternatively, you can add class for each td that contains the order info, and use jQuery method $('.class').html(html_string) to insert specific order info into your #orderDetails BEFORE you show the modal, like:
<% #restaurant.orders.each do |order| %>
<!-- you should add more class and id attr to help control the DOM -->
<tr id="order_<%= order.id %>" onclick="orderModal(<%= order.id %>);">
<td class="order_id"><%= order.id %></td>
<td class="customer_id"><%= order.customer_id %></td>
<td class="status"><%= order.status %></td>
</tr>
<% end %>
js:
function orderModal(order_id){
var tr = $('#order_' + order_id);
// get the current info in html table
var customer_id = tr.find('.customer_id');
var status = tr.find('.status');
// U should work on lines here:
var info_to_insert = "order: " + order_id + ", customer: " + customer_id + " and status : " + status + ".";
$('#orderDetails').html(info_to_insert);
$('#orderModal').modal({
keyboard: true,
backdrop: "static"
});
};
That's it. But I strongly recommend you to learn sth about ajax on Rails. It's pretty cool and efficient.

How to pass values from text area to table using AngularJS

C# MVC App using AngularJS
I am trying to display a list of values in a table that were originally entered in a text area.
Here is the workflow
User enters values in a text area as
A
B
C
When the user clicks on a button a modal window opens and should display A B C in a table .
I am trying to use angular to do this. I have tried the following:
<a class="btn btn-inverse pull-right" ng-click="arrangelist()">Arrange list</a>
<textarea id="letterlist" ng_model="letters"></textarea>
Also tried
#Html.TextAreaFor(model => model.letters, new { ng_model = "letters", #class = "width-100-percent", #rows = "7" })
And here is my modal window:
<div id=" arrangelist" class="modal hide fade" aria-hidden="true">
<table class="table">
<thead>
<tr>
<th>Letters</th>
</tr>
</thead>
<tbody>
<tr ng-animate="'table-anim'" ng-repeat="letter in letters">
<td>{{letter}}</td>
</tr>
</tbody>
</table>
<button type="button" class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
Here is the JavaScript that opens the window:
$scope. arrangelist = function() {
return $('#arrangevideos').modal('show');
}
So the modal window opens and displays the table but no values are inside the table.
How can I pass the values from the text area to the table in the modal window using Angular
Change ng_model = "letters" to ng-model = "letters".
And letters should be an array instead of string. You have to split the input to list of strings.
$scope.arrangelist = function() {
var letterplits;
letterplits = $('#letterlist').val().split('\n');
$scope.letters = letterplits;
return $('#arrangelist').modal('show');
}
you need to use ng-model, not ng_model. As long as your modal is in the same controller as your textarea, you should be able to pass it. Also, you have a space between $scope. and arrangelist. See this fiddle for a simple working example.

Categories

Resources