Closing Blazor modal with multiple modals - html

First of all, I've seen this Close Bootstrap Modal but of some reason it's not working for me.
I have a page, where one modal is called from like this
<button type="button" #onclick="#(()=>modal.Show<LandingPageHelpPopUp>())" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#myModal">Click here to get help</button>
That page's code look like this
<div class="modal-dialog" id="myModal" style="margin-left:-200px;margin-bottom:-550px;position:absolute;">
<div class="modal-content" style="background-color:gray;">
<div class="modal-body" style="color:black;">
<p>Here you can observe the controlling of the curtains by others. If the queue is empty, and you'll like the control, hit this button.</p>
<div class="modal-footer" style="float:right;border:none;margin-bottom:-25px;">
<label class="custom-close" #onclick="#(()=>modal.Show<LandingPageHelpPopUp2>())">Next page</label>
<button class="next-button" style="margin-left:-3px;"><i class="fa fa-angle-right"></i></button>
</div>
</div>
</div>
</div>
<img src="css/arrow-help.png" class="arrow-help">
From here, I'd like to see another modal. To do that, I guess I have close the first one first, in order to not create a double layer of modals - if that makes sense. That's where I have used the linked thread in the beginning, but somehow it doesn't work.
The second modal's code look like this
<div class="modal-dialog" id="myModal2" style="margin-left:-200px;margin-bottom:-550px;position:absolute;">
<div class="modal-content" style="background-color:gray;">
<div class="modal-body" style="color:black;">
<p>If other users is in the queue, click here to get in line.</p>
<div class="modal-footer" style="float:right;border:none;margin-bottom:-25px;">
<label #onclick="#(()=>modal.Show<LandingPageHelpPopUp>())">Previous page</label>
<button class="next-button" style="margin-left:-3px;margin-top:-2px;"><i class="fa fa-angle-right"></i></button>
</div>
</div>
</div>
</div>
<img src="css/arrow-help2.png" class="arrow-help2">
In my index.html I've these two scripts, that is meant to toggle the modals. That is if one modals is open, when the other one is shown, it should close.
<script>
$(function () {
$(".custom-close").on('click', function () {
$('#myModal').modal('hide');
});
});
</script>
<script>
$(function () {
$(".custom-close2").on('click', function () {
$('#myModal2').modal('hide');
});
});
</script>
Here's some screenshots, showing that the previous modal does not get closed, so it's just creating multiple layers of modals on top of each other. Here, Here, And here
Sorry for all the unnecessary code (styling, bad naming etc)
Doe any of you know why the previous modal is not getting closed, whenever the next is getting shown?

Related

Vue's v-for does not show correct text for modal window (only displays the first item's data)

I'm using Vue (just started learning it) and Bootstrap to make a blog and I want a modal window (that shows the post's name/etc) to pop up when the user clicks on the comment button. However, right now the modal window only gets the post information from the latest blog post. This means that even if you click the 1st post, you would get the id information and post title of the latest one... Any suggestions or solutions? Thanks in advance!
It seems that the main problem with my code is that it makes n numbers of modals in vue if you have n posts. I have tried slots but the modals started displaying the first post instead of the last one. I wonder if all my modals are being displayed at once but I only the last one... Should I use an index instead?
Is there any way to make only one modal that gets and display the information of the post clicked?
Here's my code of the post component
Vue.component('posts', {
props: ['post', 'loggedUser'],
template: `
<div class='blog-post py-2'>
<h3> {{post.title}} </h3>
<h6> Posted by {{post.postedBy}} on {{formatCompat(post.createdAt)}} </h6>
<span class='comments'>
<i class='far fa-comment-dots ml-3' data-toggle="modal" data-target="#commentModal"></i>
{{post.comments.length}}
</span>
</div>
`
My modal component: (mostly from the bootstrap docs)
Vue.component('modal', {
props: ['post'],
template: `
<div>
<div class="modal fade" id="commentModal" tabindex="-1" role="dialog" aria-labelledby="commentModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="commentModalLabel">Comment on {{post.postedBy}}'s post! ({{post.title}})</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
`
})
Here, I'd like the {{posted.title}} and other information to reflect the post where the comment button is clicked, but it's showing the latest post.
Parent element:
const postComponent = new Vue({
el: '#posts',
data: {
posts: null
},
methods: { // mostly code unrelated to modal stuff
}
My pug file:
#posts
if user
posts(name=username, v-for='post in posts' v-bind:post='post' v-bind:key="post.id" v-on:like-post='like' logged-user=loggedUser v-on:comment-post='comment')
modal(v-for='post in posts' v-bind:post='post' v-bind:key="post.id")
You need to add a custom data property that reflects the selected post for the template to read.
data: {
...
selected: '',
...
}
Then, you need a method that will assign the selected property to whichever post is clicked.
methods: {
changeTitle(postId) {
const currentPost = posts.filter((post) => {
return post.id == postId;
});
this.selected = currentPost.id;
}
}
So now that you have a data property to represent the current selected title, and a method to change that property with a click, you need to assign the directive for the method to the post. So, add this to the html tag you want to trigger the method:
#click = "changeTitle(postId);"
This will trigger the method along with the post id from the post that called the method. The current title can now be rendered anywhere in the template that has access to the data, like this:
{{selected}}

How to pass parameters to a modal using thymeleaf?

I just starting in a project where we're using thymeleaf and I'm new to the technology.
It's a simple modal to confirm an object to be deleted. So they want me to add the name of the item we're deleting on the message instead of a generic message like: "Are you sure you want to delete?"
They want: "Are you you want to delete Item_Name?"
So I need to pass this name as parameter.
That's the code I have the display the modal:
<button id="btnDelete" value="delete" type="button" class="btn-link" data-toggle="modal" data-object-id="12345" data-object-name="NNN" th:attr="data-object-id=''+${assignment.assignmentId}+'', data-object-name='/nonInstructionalWorkload/deleteAssignment?asssignmentId='+${assignment.assignmentId}+'', data-target='#deleteAssignmentModal'">
And that's the code I have on the modal html:
<form role="form" th:action="#{/deleteAssignment}"
name="assignmentDeleteForm" id="assignmentDeleteForm" method="post">
<div class="modal-header">
<h4 class="modal-title" id="deleteWorkItemabel">Confirm Assignment Delete</h4>
</div>
<div class="modal-body">
<div class="form-group">
<p>Assignment will be deleted, are you sure you want to proceed?</p>
<input type="hidden" id="deleteId" name="deleteId" value="nnnn"/>
</div>
</div>
<div class="modal-footer">
<button type="submit" id="btnDelConfirm" class="btn btn-primary">
Yes
</button>
<button type="button" id="btnDelCancel" class="btn btn-default" data-dismiss="modal">
No
</button>
</div>
</form>
At this point is where I need to add more information on the confirmation message about the assignment item being deleted.
Already tried some approached to get the parameters but didn't work so I'm looking for more option.
Thank you!
Thymeleaf is just template engine that takes your templeate and generate static html out of it. So passing dynamic values to your modal is a javascript work (unless you generate separate modal for each item, but this would be silly).
Using thymeleaf you have to generate a data- attribute containing desired item's name inside the button which opens modal, and that's all. You've already did such thing within th:attr:
th:attr="data-object-id=''+${assignment.assignmentId}+'', data-object-name='/nonInstructionalWorkload/deleteAssignment?asssignmentId='+${assignment.assignmentId}+'', data-target='#deleteAssignmentModal'"
The code above will generate attributes data-object-id,data-object-name and data-target inside the button. I assume that data-object-name is the one you want to use (however it looks more like an URL).
Now you can customize your modal's content using javascript. I can see, that you are using bootstrap as your frontend library, so you should take a look at this example, to have an idea how to accomplish that.
Javascript code below should work fine for you:
$('#deleteAssignmentModal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget) // Button that triggered the modal
var objectName = button.data('object-name') // Extract info from data-object-name attribute
// Update the modal's content. We'll use jQuery here, but you could use a data binding library or other methods instead.
var modal = $(this)
modal.find('.modal-body p').text('Do you want to delete ' + objectName + '?')
})
The sample project on GitHub you can clone and test it. Full video under the readme.
https://github.com/ibrahimkarayel/todoBoot/blob/master/src/main/resources/templates/home.html
<div class="modal modal-delete" th:id="modal-delete+${task.id }">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">×
</button>
<h3 id="delModalLabel">Delete Confirmation</h3>
</div>
<div class="modal-body">
<p class="error-text"><strong>Are you sure you want to
delete this task ?</strong></p>
</div>
<div class="modal-footer">
<button class="btn " data-dismiss="modal" aria-hidden="true">
Cancel
</button>
<a th:href="#{/task/delete/{id}(id=${task.id})}">
<span class="btn btn-danger" value="delete">Delete</span></a>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!--end delete modal-->
<script>
$('#modal-delete').on('show.bs.modal', function (e) {
$(this).find('.btn-ok').attr('href', $(e.relatedTarget).data('href'));
$('#modal-deleteHiddenId').val($(this).find('.btn-ok').attr('href'));
});
</script>

Successive bootstrap accordion entries are increasingly large?

I'm using Bootstrap to display a list of people from an SQL server in an accordion (expandable list).
My problem is that there is an increasing amount of whitespace between consecutive entries in the accordion, which I can't get rid of.
Its easiest to see it in action: http://ec2-54-200-151-237.us-west-2.compute.amazonaws.com/#
When the whitespace is clicked the tab above is opened, which is some clue to what is going wrong - however I am quite new to html and javascript.
Here is the javascript that creates the new panel:
function create_panel(first_name, last_name, idx){
var $template = $(".template");
var $newPanel = $template.clone();
$newPanel.find(".collapse").removeClass("in");
$newPanel.find(".accordion-toggle").attr("href", "#" + String(idx))
.text(last_name+" "+first_name);
$newPanel.find(".panel-collapse").attr("id", idx).addClass("collapse").removeClass("in");
return $newPanel;
}
And the html panel group element:
<div class="panel-group" id="accordion1">
<div class="panel panel-default template" style="display:none">
<div class="panel-heading accordion-toggle" data-toggle="collapse" data-parent="#accordion1" href="#collapse20" style="width:100%;">
<a class="panel-title">
Mr. Template <span class="label label-danger" style="float:right">Urgent</span>
</a>
</div>
<div id="collapse20" class="panel-collapse collapse">
<div class="panel-body">
<div class="btn-group">
<button type="button" class="btn"><i class="glyphicon glyphicon-flag"></i></button>
<button type="button" class="btn"><i class="glyphicon glyphicon-earphone"></i></button>
<button type="button" class="btn"><i class="glyphicon glyphicon-ok"></i></button>
</div>
</div>
</div>
</div>
</div>
If anyone can help me see where the problem is, I'd be extremely grateful.
Thanks in advance
I solved this just after posting.
The fact that the extra whitespace was compounding tipped me off:
The javascript was referring to the last created item .template every time it made a new entry - hence the compounding. I added id=template to the panel element and changed the javascript refererence to #template, and the accordion now looks normal.

How do I link each modal window to the specific image that the user clicks on to open them?

I've looked for solutions online and it seems that there's something called the data-attribute that I can use to do what I want.
I have two different modal windows, each with its own content, and I want to link each of them to a specific button (or in my case, an image that the user will click on). I tried putting in the "data-attribute", but the second modal window (the one with the id, fujian), is not popping up when I click on the corresponding image.
Does anyone have any suggests or ideas as to why this isn't working and what I should do?
<!--The two image icons that user clicks on-->
<a href='#' onclick='overlay()'><img src="city1.png" alt="sichuan" class="city1"/></a>
<img src="city2.png" alt="sichuan" class="city2"/>
<div id="overlay">
<!--The two separate modal windows-->
<div class="modal">
<img src="sichuan.png" alt="sichuan popUp"/>
<a class="closing" href='#' onclick='overlay()'><img src="/Users/KarenLee/Desktop/exit.png"></img></a>
</div>
</div>
<div id="overlay">
<div class="modal" id="fujian">
<img src="fujian.png" alt="fujian popUp"/>
<a class="closing" href='#' onclick='overlay()'><img src="/Users/KarenLee/Desktop/exit.png"></img></a>
</div>
</div>
And here is my overlay() function if you need to see it:
function overlay() {
el = document.getElementById("overlay");
el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
}
id's must be unique through out the document and you have repeating id <div id="overlay">
You can achieve with single modal what you are trying to achieve with 2 modals with data-attributes
Missing key div elements in modal HTML and that's why with your code only modal-backdrop is showing, nothing else
as far you asked about data-attribute, the anchor <a></a> element has two custom data attributes: data-toggle and data-target.
The toggle tells Bootstrap what to do and the target tells Bootstrap which element is going to open.
So whenever <a></a> link like that is clicked, a modal with targeted id will appear.
let's suppose you have 2 images and wants to show in modal, opening modal with default bootstrap behaviour and also can pass the image to modal using data-attributes which in this case data-image and using bootstrap modal event listener, can show the image in modal when modal open (no need of 2 modals)
<a data-target="#fujian" data-toggle="modal" data-image="http://tympanus.net/Tutorials/CaptionHoverEffects/images/1.png" class="btn btn-primary">Image 1</a>
<a data-target="#fujian" data-toggle="modal" data-image="http://tympanus.net/Tutorials/CaptionHoverEffects/images/2.png" class="btn btn-warning">Image 2</a>
And Modal HTML will be
<div id="fujian" class="modal fade">
<div class="modal-dialog"> //Missing this Div
<div class="modal-content"> //Missing this Div
<div class="modal-body">
<img class="showimage" src="" /> //Image will be shown Here
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
and bootstrap event listener
$(document).ready(function () { //Dom Ready
$('#fujian').on('show.bs.modal', function (e) { //Event listener
var image = $(e.relatedTarget).data('image'); //Fetch image url from modal trigger <a> link
$(".showimage").attr("src", image); //load image in modal
});
});
Fiddle

MVC 4 Bootstrap Modal Edit \ Detail

Hoping someone might be able to help me with something I am experimenting with in MVC 4 using bootstrap.
I have a strongly-typed index view which displays items in a table along with edit and delete action icons in each line.
#model IEnumerable<Models.EquipmentClass>
....
#foreach (var item in Model)
{
<tbody>
<tr>
<td>
#item.ClassId
</td>
<td>
#item.ClassName
</td>
<td>
<a href=#Url.Action("Edit", "EquipmentClass", new { id = item.ClassId })>
<i class="icon-edit"></i>
</a>
<a href=#Url.Action("Delete", "EquipmentClass", new { id = item.ClassId })>
<i class="icon-trash"></i>
</a>
</td>
</tr>
</tbody>
} <!-- foreach -->
The EquipmentClass controller returns the Edit view for the selected item based on the id. All great and as expected at this point
public ViewResult Edit(int id)
{
return View(equipmentclassRepository.Find(id));
}
What I would like to know is how to open the edit form in a bootstrap modal dialog.
I could try and substitute the edit action in the table with the following and then have a modal div at the bottom of the view but how do I pass in the ID of the selected item and which html helper should I use in the modal section?
<!-- replaced table action -->
<a class="btn pull-right" data-toggle="modal" href="#myModal" >Details</a>
....
<!-- modal div -->
<div class="modal hide fade in" id="myModal" )>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h3>Modal header</h3>
</div>
<div class="modal-body">
#Html.Partial("Edit")
</div>
<div class="modal-footer">
Close
Save changes
</div>
</div>
I'd greatly appreciate any advice, many thanks
I think that I have a solution to your problem. To make your MVC application work as you want it to you should make some changes to the code you provided:
1. Add a div representing a modal for editing an item at the bottom of your layout page:
<div id="editModalContainerID" class="modal hide fade" data-url='#Url.Action("Edit", "EquipmentClass")'>
<div id="editModalBodyID"></div>
</div>
Notice that this modal is strictly connected to the controller action responsible for editing an EquipmentClass item.
2. Add a jQuery function to your custom javaScript:
function showModal(modalContainerId, modalBodyId, id) {
var url = $(modalContainerId).data('url');
$.get(url, { id: id }, function (data) {
$(modalBodyId).html(data);
$(modalContainerId).modal('show');
});
}
As you can see this function takes id as one of its parameters. In general its purpose is to replace the empty modal body with what we will put in a separate partial view and than display whole container as a modal page.
3. Put your modal div in a separate partial view, and call it Edit (has to be the same as your controller action name). You will have to change your Edit partial name to sth else, for example EditBody.
The Edit partial view should now look sth like this:
#model EquipmentClass
<!-- modal div -->
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h3>Modal header</h3>
</div>
<div class="modal-body">
#Html.Partial("EditBody", Model)
</div>
<div class="modal-footer">
Close
Save changes
</div>
4. Change the controller action so that it returns the partial view created in the previous step:
public PartialViewResult Edit(int id)
{
return PartialView(equipmentclassRepository.Find(id));
}
5. Change the edit 'a' anchor so that it calls created jQuery function:
#model IEnumerable<Models.EquipmentClass>
....
#foreach (var item in Model)
{
<tbody>
<tr>
<td>
#item.ClassId
</td>
<td>
#item.ClassName
</td>
<td>
<a data-toggle="modal" onclick="showModal('#editModalContainerID', '#editModalBodyID', #item.ClassId)">
<i class="icon-edit"></i>
</a>
<a href=#Url.Action("Delete", "EquipmentClass", new { id = item.ClassId })>
<i class="icon-trash"></i>
</a>
</td>
</tr>
</tbody>
} <!-- foreach -->
This way each time an 'a' anchor with edit icon is clicked the showModal function (with related id being passed) is fired and a bootstrap modal with related data is displayed.
I'm sure there is a better way to do it, but this way worked for me just fine :)
Hope this helps you a bit :)
Przemo answer worked for me, however do note that I only managed to get it to work when I changed the first block of code from
<div id="editModalContainerID" class="modal hide fade" data-url='#Url.Action("Edit", "EquipmentClass")'>
<div id="editModalBodyID"></div>
</div>
to
<div id="editModalContainerID" class="modal fade" data-url='#Url.Action("Edit", "EquipmentClass")'>
<div id="editModalBodyID"></div>
</div>
Notice that I removed the "fade" class from editModalContainerID. Otherwise the partial view does not load. Hope this helps anyone else with the same issue.