Semantic-ui modal duplicated with VueJS - javascript

I found 2 similar questions ont stackoverflow, but it didn't help.
I'm using VueJS and semantic-ui modal.
According to my structure of code, each time i call the "show modal" method, a new modal is added to the source page with the same id :
<div id="myModal ...>
So finally the content of this modal is wrong and not expected because the changes are in the last modal (conflict id). But anyway duplicating the modal code is wrong.
So i made a jsfiddle to be clear : https://jsfiddle.net/3ut5d9uu/5/
To reproduce the bug :
click on "open modal", you see the name "a"
click on "change name", open modal, the name has changed (just appending "x"), this is ok. You can repeat if you want.
click on "change page", you go to page 2, click again to go to page 1
"change name" has now no effect in the modal content.
Help to debug : i can see in my developement browser that each time "openModal" is called, a full code is added at the end at the DOM and never removed :
<div class="ui dimmer modals page inverted transition hidden">
<div id="myModal"...
So we have several same ids "myModal".
But i could'nt fix that.
Thanks for your help.

As mentioned in the comment, there's a conflict between vue and jquery
Vue uses a shadow dom that adds and removes items as needed
jQuery relies on the item remaining in the DOM the entire time.
this conflict happens when you go from one page to another.
While I would strongly recommend removing jquery, in favour of something like https://github.com/almino/semantic-ui-vue2, there is a way to handle this.
here is the working fiddle
https://jsfiddle.net/3ut5d9uu/6/
this is done through a couple key things,
maintaining scope of dome by tracking it within vue. Here we assign reference to the jQuery modal object to a vuew data object
,mounted: function () {
this.modalDom = $('#myModal').modal({ inverted: true, closable: false });
}
you will also need to add modalDom to data
let dataPage1 = {
name: 'a',
modalDom: null
};
and then use that to show/hide modal
openModal: function() {
this.modalDom.modal('show');
},
closeModal: function() {
this.modalDom.modal('hide');
},
voilà, Bob = yourUncle;

Related

Bootstrap Modal and Jquery: [DOM] Found 2 elements with non-unique ids, however all IDs are unique

Okay so I use bootstrap 4, and I have two different modal types in a single page. I use Ajax to fill up the body of these modals. Both of these forms that each modal opens are different from each other but they have certain ID tags that are similar.
This is how I fire up my modals.
$('#modalForm').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget);
ajaxLoad(button.data('href'), 'modal_content');
});
$('#modalFormLG').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget);
ajaxLoad(button.data('href'), 'modal_content_lg');
});
The problem is when I open one modal, and then when I open the second one, I get the following error in the browser console.
[DOM] Found 2 elements with non-unique id #cashpaid: (More info: goo...)
However, I don't have any duplicates of IDs, it's just so that cashpaid ID is being used in both of those forms that each of these modals calls up into its body.
If I refresh the page and open the modal again, then I don't see this problem.
I have tried the following but it didn't have any effect on it
$("#myModal").on("hidden.bs.modal", function(event) {
$(this).removeData("bs.modal");
});
When I run the following two, then my modals becomes unresponsive for future use because they essentially delete that particular html data.
$("#myModal").on("hidden.bs.modal", function(event) {
$(this).empty();
});
AND
$("#myModal").on("hidden.bs.modal", function(event) {
$(this).remove();
});
After opening and submitting the first modal, in the browser console when I type, "cashpaid" for example, I see the following.
<input type="number" id="cashpaid" name="cashpaid" min="0">
However, when I open the second modal and submit that form and when I type "cashpaid" in the browser console, I see the following.
HTMLCollection(2) [input#cashpaid.valid, input#cashpaid, cashpaid: input#cashpaid.valid]
So is there any method for bootstrap 4 modals to purge the remote url form's data when it closes down?
Any help would be greatly appreciated. Thanks in advance.
$(document).on('hidden.bs.modal', '#modalForm', function (event) {
$('.modal-body', this).empty();
});
...will remove all child elements of #modalForm .modal-body after the closing modal animation ends.
Note 1: you only need to bind this once, not every time you open the modal.
Note 2: If you want this functionality on every modal (not only #modalForm), replace #modalForm with .modal. But keep in mind you can only do this with modals that get their contents generated upon reopening. A static modal will remain empty when reopened.

How can I reuse a cloned element?

I have a Bootstrap modal on my page. Basically, what happens is the user picks some options on the page, clicks a go button and that modal pops up and gets populated with the live output of the job they started.
After the job runs, I'd like for the user to be able to close the modal, choose more options, and run the job again. The problem is, I can't seem to get rid of the output from the previous job.
I tried this answer, which was to clone the div and use replaceWith() to restore the content to it's original state. This works for the first two times (job runs once, then when you start another the modal is back to it's original state), but for any time after that, the modal pops up with the content of the previous run until it's text gets overridden.
I have this at the beginning, to capture the contents before anything is done:
$(document).ready(function() {
modalHold = $("#postModal").clone();
});
And, this runs when the modal closes:
$('#postModal').on('hidden.bs.modal', function (){
$("#postModal").replaceWith(modalHold.clone());
})
I would've expected the replaceWith(modalHold.clone()) to replace it with a new clone of the original element, however it seems that I'm still modifying the original. Any help would be appreciated, or if there's a better way of doing this I'd be glad to hear it.
Bootstrap does some javascript magic with the Modal, so I guess you can't just clone whole the Modal's HTML. As a workaround you may try to play with class="modal-body" node only, clone and replace it.
But the truth is on another way. You need to implement a function which would reset your inputs and call it each time the Modal is being hidden.
var modalDefault = {
input1: '',
input2: 'Hello!'
};
var resetModal = function() {
$('#modalInput1').val(modalDefault.input1);
$('#modalInput2').val(modalDefault.input2);
}
// ...
$('#postModal').on('hidden.bs.modal', resetModal);
Not sure why I didn't think of this to begin with, but dhilt's answer helped point me in the right direction. The idea of creating defaults and just switching back to those could be helpful in some cases, but I had some content (including job info and a loading bar) inside the modal that I'd really like to be displayed each time a job starts, until it is done and the output can be displayed.
Instead of doing any fancy cloning, I placed that content into a div and just grabbed its innerHTML:
$(document).ready(function() {
modalHold = $('#jobOutputHolder').html();
});
When the .load () runs, it will update #jobOutputHolder with the output of the job. Then, on hide of the modal:
$('#postModal').on('hidden.bs.modal', function (){
$('#jobOutputHolder').html(modalHold);
})
With this method, I can run a job, see the loading screen, see the job output, close the modal, and repeat as many times as I need without ever seeing the output of previous jobs.

Unable to close closable tabs and to activate tabs

I made a fiddle which demonstrates these issues. The first issue is that it is impossible to close closable tabs in a TabBar. The code is as simple as:
Ext.create("Ext.tab.Bar",{
renderTo: "one",
items:[{"text":"One","closable":true},{"text":"Two","closable":true}]
});
Documentation says, that
closable : Boolean bindable
True to make the Tab closable and display the close icon
So, this property is not only about this close icon, but also about this behaviour to be closed.
The second issue I face is that it is impossible to activate tabs added to a tabpanel through a tabbar. The code is also very simple:
Ext.create("Ext.tab.Panel",{
renderTo: "two",
id: "test2",
items:[{"title":"One","closable":true},{"title":"Two","closable":true}],
listeners: {
render: function () {
this.getTabBar().add({"text":"Three"});
}
}
});
Just try to activate this last tab and you will fail. And if you set active property on this tab, then you won't be able to deactivate this tab. So, how can we fix all this?
TabBar is used internally by a Ext.tab.Panel and typically should not
need to be created manually.
The tabbar's implementation relies on the fact that it is a part of a tabpanel. If we dig in it's source, we will see that in the "closeTab" method implementation it checks if there is an underlying card to close:
if (tabPanel && card) {...
Related to the second behavior, if you will check out the "doActivateTab" method implementation, also in the tabbar source code, this is what you will see:
doActivateTab: function(tab) {
var tabPanel = this.tabPanel;
if (tabPanel) {
// TabPanel will call setActiveTab of the TabBar
if (!tab.disabled) {
tabPanel.setActiveTab(tab.card);
}
} else {
this.setActiveTab(tab);
}
}
So if there is no tabpanel, it will just activate the tab, if there is, it will call the tabpanel's "setActiveTab", that if it doesn't find a card attached to the tab-to-be-activated, activates the previous tab.
You should not add directly to the tabbar, instead add to the tabpanel:
this.add({"title":"Three"});
Here's a working fiddle. Seems like setactivetab needs to be after render.

Bootstrap Popover AND a Modal (hover and click)

Scenario: user profile. I would like to be able to display a user name with a popover that displays a limited amount of information from the user profile. So far, I have that part working. I can build it on the fly and have it do what I need. The popover works perfectly.
What I would also like to do is have the user be able to click on the user name and bring up a Bootstrap modal form with more information about the user (if provided). The first problem I am seeing is that it appears the data-toggle attribute can only have a single setting:
echo '' . $user_row['user_name'] . '';
In that example, if I add the modal to the data-toggle attribute it doesn't seem to do me much good.
I have discovered by tinkering (and that is why the class 'userprof' in the code above), that a JavaScript click event can be triggered (right now all I'm doing is a basic JS alert dialog to test), but from there I would want to load the modal. I am not sure if I can make it all work.
I have a set of functions I've used successfully for another modal (calling this one 'userModal') that I got some help from someone here a while back with -- is it possible to call that from the click event?
// code to open the modal with the caption and description:
$('#userModal').on('show.bs.modal', function (event)
{
var button = $(event.relatedTarget); // Button that triggered the modal
var title = button.data('title'); // Extract info from data-* attributes
var body = button.data('body'); // Extract info from data-* attributes
var modal = $(this);
modal.find('.modal-title').text( title );
modal.find('.modal-body').append( body );
});
// when modal closes, clear out the body:
$('#userModal').on('hidden.bs.modal', function ()
{
$(this).find(".modal-body").text('');
});
Since these are "anonymous" functions I am not sure I can call them ... feeling a bit lost in the code here. Any help pointing me in the right direction would be great. I'd even be willing to consider a different idea, but I would like this kind of functionality (hover and click) for this situation and possibly something else. Thanks!
You're listening for the modal to show itself, when the DOM is showing the modal.
try using something like this, and use a button or a link with data-toggle="modal"
$(document).on('hidden.bs.modal', '#userModal', function ()
{
$(this).find(".modal-body").text('');
});
for reference https://jsfiddle.net/y063mu4t/1/
You can try:
$(document).on('click', 'a.userprof', function(){
$('#userModal').modal('show');
});
To make your callback function work, you need to add according data-* attribute to each of the <a> tag.

reset jquery smartwizard

I am using jquery smartwizard
My wizard opens in a dialog when a user clicks on a button named "create". When the user clicks the button again, I want the wizard to reset and start a fresh wizard but it retains its state. If i reinitialize it, then it adds the next, previous and finish buttons again and messes the entire wizard UI. Any ideas how I can reset the smart wizard?
Wizard reset public method is included in the latest Smart Wizard 4, see the example.
$('#smartwizard').smartWizard("reset");
Calling this function will reset the wizard to the initial default state.
Depending on which dialog you are using, I think what you will need to do is the following:
Create a template for your wizard element that is hidden
When you open the dialog (onOpen), clone the element and apply the smartwizard
When the dialog is closed, remove the element that you've cloned.
Here is a demo using colorbox:
http://jsfiddle.net/lucuma/Kn2ud/4/
Edit: Since the fiddle is no longer working due to the movement of libraries from when it was created, the code is below:
$("button").colorbox({
inline: true,
open: true,
width: "1000px",
href: '.inline',
onClosed: function() {
$('.inline .swMain').remove();
},
onOpen: function() {
$('.template').clone().removeClass('template').appendTo('.inline').smartWizard({
transitionEffect: 'slideleft',
onFinish: onFinishCallback
});
}
});
This seems to work for me (in coffeescript, but you get the idea).
numSteps = 5
wizardDiv.smartWizard('goToStep', 1)
# disable all the following steps
for i in [2..numSteps]
wizardDiv.smartWizard('disableStep', i)
Clearing out or retaining any data in the wizard itself is up to you.

Categories

Resources