How to show a modal only once per user? - javascript

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));
})
}
});

Related

Reference a confirmation window from forloop

I've been trying to create a popup delete confirmation overlay from a forloop. I can't make it work or define which ids or how to pass identifiers for the overlay.
I got this, but it only refers the first element of the loop. I tried serialize the ids with the element pk (myNavRef{{ref.pk}}), but doesn't work
{% for ref in perf_bim.referenciapredio_set.all %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<th>{{ref.rol_fk.rol}}</th>
<th>{{ref.rol_fk.dir}}</th>
<td><img src="{% static 'arrow.png' %}" height=20 alt=""></td>
<td><button onclick="openNavRef()" type="button" class="btn btn-outline-dark btn-sm"><img src="{% static 'trash.svg' %}" alt="" height=15 ></button><br></td>
</tr>
<div id="myNavRef" class="overlay">
<div class="fontformat"style="padding-top:250px;width:40%;margin:auto;">
<div class="overlay-content">
Eliminar Referncia de Predio Rol: {{ref.rol_fk.rol}}
<br>
Cancelar
</div>
</div>
</div>
{% endfor %}
<script>
function openNavRef() {
document.getElementById("myNavRef").style.display = "block";
}
function closeNavRef() {
document.getElementById("myNavRef").style.display = "none";
}
</script>
thanks!!
If you want to display the corresponding div then you can define the div with unique id. Then you can show corresponding div with the provided id of the element.
First set your div element with unique id as
<div id="myNavRef{{ref.pk}}" class="overlay">
Then on your button element onclick pass the same id as
<button onclick="openNavRef('{{ref.pk}}')" type="button" class="btn btn-outline-dark btn-sm">
Also for your close button as
Cancelar
Then in your javascript
<script>
function openNavRef(id) {
document.getElementById("myNavRef" + id).style.display = "block";
}
function closeNavRef(id) {
document.getElementById("myNavRef" + id).style.display = "none";
}
</script>

Modal doesn't come with input's values

I have to use modals in my project. But unfortunately it does not work well.
On the page, when I click on the Add New Role button, everything goes right. But then when I click on the role edit button, the modal is displayed with blank values. While the IDs are successfully sent to the action.
After that when you reload the page, and first click on the edit role button, the modal will not display at all. At the same time, if you click the Add New Role button again, the modal is successfully displayed and everything is OK. At the same time, if you click the role edit button again, the modal will be displayed again in blank. (Just as before the IDs were successfully sent to the action but not found). I think this problem is related to two things:
The problem is with the action (maybe the code I wrote didn't send
the values well)
The problem may be that the following JQuery codes is not
performing well:
Jquery (file name: application-role-index.js):
(function ($) {
function RoleList() {
var $this = this;
function initilizeModel() {
$("#modal-action-application-role").on('loaded.bs.modal', function (e) {
}).on('hidden.bs.modal', function (e) {
$(this).removeData('bs.modal');
});
}
$this.init = function () {
initilizeModel();
}
}
$(function () {
var self = new RoleList();
self.init();
})
}(jQuery))
Anyway i hope you can help me. Here is the code I will use for this section:
Action in 'RoleListController':
[HttpGet]
public async Task<IActionResult> AddEditRole(string Id)
{
RoleListViewModel model = new RoleListViewModel();
if (!string.IsNullOrEmpty(Id))
{
ApplicationRole applicationRole = await _roleManager.FindByIdAsync(Id);
if (applicationRole != null)
{
model.Id = applicationRole.Id;
model.Name = applicationRole.Name;
model.Explanation = applicationRole.Explanation;
}
return PartialView("_AddAndEditAppRole", model);
}
else
{
return PartialView("_AddAndEditAppRole");
}
}
The View page i'm using modal:
<div class="btn-group">
<a class="btn btn-primary" id="showaddrole" data-toggle="modal" asp-action="AddEditRole" data-target="#modal-action-application-role">افزودن نقش جدید</a>
</div>
<table dir="rtl" class="table table-bordered table-striped myTable table-condensed">
<thead>
<tr>
<th>ID</th>
<th>#Html.DisplayNameFor(Model => Model.Name)</th>
<th>#Html.DisplayNameFor(Model => Model.Explanation)</th>
<th>#Html.DisplayNameFor(Model => Model.NumberOfUsers)</th>
<th>عملیات</th>
</tr>
</thead>
<tbody>
#foreach (var role in Model)
{
<tr>
<td>#role.Id</td>
<td>#role.Name</td>
<td>#role.Explanation</td>
<td>#role.NumberOfUsers</td>
<td>
<a class="btn btn-info myTableIC" asp-route-id="#role.Id" asp-action="AddEditRole" data-target="#modal-action-application-role" data-toggle="modal">
<i class="glyphicon glyphicon-pencil"></i>
</a>
<a class="btn btn-danger myTableIC" asp-route-id="#role.Id" asp-action="DeleteRole">
<i class="glyphicon glyphicon glyphicon-remove"></i>
</a>
</td>
</tr>
}
</tbody>
</table>
#Html.Partial("_Modal", new BootstrapModel { ID = "modal-action-application-role", Size = ModalSize.Medium })
#section Scripts{
<script src="~/js/modal-js/application-role-index.js"></script>
}
I have prepared a short video of how my program works so you can move forward with a better understanding:
You can find that by this link...
i suggest a solution at first create a div block with a unique id
<div id="popup"></div>
than use ajax to call the action like this :
$("#btnAdd").click(function () {
$.ajax({
type: 'POST',
url: '#Url.Action("AddEditRole")',
success: function (result) {
$("#popup").html(result);
$("#popup-addRole").modal("show");
}
});
});
then create an partiel view of popup with the id of model is popup-addRole something like this
<div class="modal" id="popup-edt" role="dialog">
<div class="modal-dialog" role="document" style="width:50%;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
//add your form here
</div>
</div>
</div>
</div>
don't forget to add model you want to use
i hope that fix the problem

bootstrap modal displays twice

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});
});
});

MVC - Html.Action to retrieve element using Javascript, then pass it as parameter to Controller, then return a PartialView

View - My view has a modal that has an #Html.Action that calls the PartialViewResult in Controller. Notice the #Html.Action("RetrieveItemPrice", new { item_Id = 1 }) still has predefined item_Id.
Q#1: How do I create a function that will get an element's value and put it in the item_Id parameter before sending it to the Controller? Could this be inserted in the #Html.Action?
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<div id="pvPrice" class="" style="border: 0px solid green; ">
#Html.Action("RetrieveItemPrice", new { item_Id = 1 })
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<table id="dbTable">
<thead>
<tr>
<th class="hidden">
#Html.DisplayNameFor(model => model.itemId)
</th>
<th>
#Html.DisplayNameFor(model => model.itemName)
</th>
</tr>
</thead>
<tbody id="dbBody">
#foreach (var item in Model.Items)
{
<tr>
<td class="hidden">
#Html.DisplayFor(modelItem => item.itemid)
</td>
<td>
#Html.DisplayFor(modelItem => item.itemname)
</td>
</tr>
}
</tbody>
</table>
Controller
public PartialViewResult RetrieveItemPrice(string item_Id)
{
var prices = from ip in _odb.ITEM_PRICE_MSTR
join i in _odb.ITEM_MSTR on i.ITM_ID equals i.ITM_ID
select new ItemModel
{
itemid = i.ITM_ID,
itemname = i.ITM_DESC,
itemprice = ip.ITM_PRICE,
defaultflag = ip.DEFAULT_FL,
startdate = DbFunctions.TruncateTime(ip.START_DT),
enddate = DbFunctions.TruncateTime(ip.END_DT),
createddt = i.CREA_DT
};
prices = prices.Where(i => i.itemid.ToLower().Contains(item_Id.ToLower()));
prices = prices.OrderByDescending(i => i.itemprice);
var vm = new ItemViewModel();
vm.Items = prices.ToPagedList(pageNumber, pageSize);
return PartialView("_ViewItemPrice", vm);
}
Q#2: When I return a PartialView in Controller using PartialViewResult, who's going to receive and display it in the View? I ran the code, but nothing is being displayed. I think I still lack codes in View to receive the returned PartialView in Controller
Assuming you have many items with different item_Id and you want to show the modal dialog when this item is clicked. You should be listen to the click event on the element, make an ajax call and get the response (partial view result) and use that to build your modal dialog content.
Assuming your main view has code like this
<table>
#foreach (var item in Model.Items)
{
<tr>
<td>#item.itemname</td>
<td><a href="#Url.Action("RetrieveItemPrice",new { item_Id = itemId})"
class="modal-link" >#item.itemname</a>
</td>
</tr>
}
</table>
<!-- The below code is for the modal dialog -->
<div id="modal-container" class="modal fade" tabindex="-1" role="dialog">
X
<div class="modal-content">
<div class="modal-body"></div>
</div>
This will generate links with css class modal-link for each item in the table. The href value of the links will be like YourControllerName/RetrieveItemPrice?item_id=123(123 will be replaced with actual itemid) Now listen to the click event on these, make an ajax call to the href attribute value of these links and use the response for populating the modal dialog content.
$(function () {
$('body').on('click', '.modal-link', function (e) {
e.preventDefault();
$("#modal-container").remove();
$.get($(this).attr("href"), function (data) {
$('<div id="modal-container" class="modal fade">
<div class="modal-content" id="modalbody">'
+ data + '</div></div>').modal();
});
});
});
This code will replace the entire content of the modal with the partial view result coming from the RetrieveItemPrice action method. That means you need to include the necessary markup needed for the modal header and footer(with buttons) in the _ViewItemPrice partial view.
A#1: the code calling #Html.Action is executed on server-side, at that phase the html document has not been sent to client-side so you don't have to look for a way to retrieve element value. You can pass it directly to the call, instead, because the model used for rendering the view (including the element) should be accessible to the code in the modal.
If you place the modal markups right inside the view, you definitely can get #Model.ItemId, for example.
If you place the modal in a partial view, you can pass item id via ViewBag:
#Html.Partial("Modal", null, new ViewDataDictionary{{"ItemId", Model.ItemId}})
then use it in the modal markups:
#Html.Action("RetrieveItemPrice", new { item_Id = ViewBag.ItemId })
A#2: you should try if [ChildActionOnly] makes the action RetrieveItemPrice works.

Django Angularjs How to call Http request with specific Id

i am very new in angularjs.I am trying to pull data in one of my django template using angularjs.This is the view by which i actually trying to pull data.
def download_history(request,download_id):
from django.core import serializers
download_history = DownloadHistory.objects.filter(user = request.user,pk=download_id)
ctx_detail_history = serializers.serialize('json', download_history)
return HttpResponse(ctx_detail_history)
this is the urls
url(r'^history_detail/(?P<download_id>\d+)/$',views.download_history,name = 'download_history'),
and this is my template where i am trying to pull data and trying to show in a jquery pop up modal.
{% extends 'base.html' %}
{% block title%}User Subscription {%endblock%}
{%block content%}
<div style="margin-top:100px;background-color:#85ADFF;" ng-app='history'>
<table class="table table-striped" >
{%for download_history_name in download_history%}
<tr>
<td><button type='button' data-toggle="modal" data-target="#myModal"><a href={%url 'download_history' download_history_name.id %} >{{download_history_name.name}} and the id {{download_history_name.id}}</a></button></td>
</tr>
{%endfor%}
</table>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Objact Name</h4>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table table-striped" ng-controller='HistoryCtrl'>
<tbody>
<tr>
{[{detail_history.fields.name}]}
{[{detail_history.fields.download_rate}]}
{[{detail_history.fields.photo.url}]}
{[{detail_history.fields.downloaded_time}]}
{[{detail_history.fields.DuePayment}]}
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
{%block extrajs%}
<script>
var app = angular.module('history',[]);
app.config(function($httpProvider){
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
});
app.config(function($interpolateProvider){
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
});
app.controller('HistoryCtrl',['$scope','$http' , function($scope,$http){
$http.get('/history/history_detail/(? P<download_id>\d+)/').success(function(data){
//$scope.doToggle=false;
$scope.detail_history=data;
}).error(function(data,status){
$scope.data = data || 'Request Fails';
$scope.status = status;
console.log(data)
});
}]);
</script>
{%endblock%}
{%endblock%}
now the problem is ,though i am trying to pull data with a specific id,but its not working,, in fact if i inspect the page ,it shows the return URL something that
http://localhost:8000/history/history_detail/(?Pd+)/
now whats the problem,definitely i make a mistake here,but i am very new in angularjs and can not figure it out.Is it possible to solve the problem using ng-click function?
From a cursory examination of your JavaScript it appears that you're trying to make a GET request to a URL including a regular expression. This makes sense for your Django configuration because you're telling the application to expect a number in the url that you assign to a variable named download_id. It appears you have copied this URL directly into your JavaScript where in fact you should be providing a specific download id in your GET request (e.g. '/history/history_detail/12345/').

Categories

Resources