vue-js button element with no type --> submit - vue.js

We have been having a very strange problem in a vue-js (#vue-cli, Build version) application. There was a button in App.vue that had an onclick
<button #click="goIRList" id="irlistBtn">IR List</button>
that was working for fine for some users, every time, and not others. For the others, I checked (with alerts) that the goIRList code was not reached at all. These others had this issue with any browser we tried. They did not have the issue when Vue+Developer Tools was open - making it harder for me to debug it.
Instead of the goIRList code, these users got a page with just the error message
Cannot GET /menu.csp
That was especially perplexing, because menu.csp is code from a completely different system, though one also associated with the same computer. It is never referenced in the vue-js application.
Eventually I realized that what was happening was a submit, even though the button was not in any form on the page [I had thought that a button is only a submit type by default, if it is inside a form]. As soon as I added a type, <button type="button"...>, the issue went away completely.
Could someone explain why this was happening? And why did it work for some users? Thanks!
Update: and now the problem is back, same conditions: for them and not for me. Nothing changed. I also added .prevent to the button's onclick:
<button type="button" #click.prevent="goIRList" id="irlistBtn">IR List
and no help. So maybe that wasn't the issue. Anyhow, now I'm asking for a fix as well as an explanation. Thanks!

Add a "submit" event catcher in the form, and prevent the default action.
<template>
<div id="app">
<form #submit="submit">
<input value="Tom">
<button>Submit</button>
</form>
</div>
</template>
<script>
export default {
name: "App",
methods: {
submit(e) {
e.preventDefault();
console.log("Success!");
}
}
};
</script>

And someone pointed out the answer to me. Ridiculous: those two buttons were hidden underneath a logo image that was higher up on the page. It was the image that contained the bogus link.
I never got the error, because I can't see so well, so I keep the sizing high, and the buttons were far away from the logo. Others had a more normal page sizing, and everything got smaller except for that image; the invisible margin of the image went over the buttons, and someone trying to click on the buttons triggered the link.
I set the image to resize with the page and all is well.

Related

Vuejs #click event works wrong from time to time

Recenty, I noticed that the checkboxes that I wrote a click event worked incorrectly from time to time. Not everytime but sometimes their #click event works in reverse. Here is what I am trying to tell;
<label class="form-switch">
<input type="checkbox" #click="showElement = !showElement"/>
</label>
I have a simple form switch and there are some css on it which I didn't put here, it looks like a toggle switch. It toggles a data which is showElement. The default state of the data is false and when you click on the toggle it becomes true and false respectively.
<div v-show="showElement>
some content here
</div>
When the showElement is true I want to display the above div, and when it becomes false, I want it to be hidden. There is no problem with that. But here is my question;
If my observation is corret, usually when the project is started for the first time, in other words, when I type npm run serve and start the project, I immadiately go and check if it is working fine or not so I click on the checkbox very quickly over and over andsometimes the click event breaks down and starts working backwards. I mean, when the switch is off, the content is visible, when it is false, the div is showing, but it should be reversed. This happens sometimes when I browse the other pages of the project and return to this component. Is this a bug? Or am I doing something wrong? In the first version of the code it was like below;
<label class="form-switch" #click="showElement = !showElement>
<input type="checkbox"/>
</label>
I accidentally typed the click event to the label element instead of input. I thought that might be the problem. I am still thinking that is the problem but the bug that I explained above still happens sometimes. Do you know why? Can anyone explain?
Usually i find that with checkboxes in VueJS #Click is not the way to go. Try to use #Change event instead. This should make it more consistent.
The reason behind this is that the click event triggers before the value has been updated. Therefore creating the risk of it overwriting the old value instead of the newly updated one
EDIT:
I actually think in this case you might even be able to get around this by simply adding a v-model to the checkbox like so:
v-model="showElement" instead of having either #click or #change.
Verison 1:
<label class="form-switch">
<input type="checkbox" #change="showElement = !showElement"/>
</label>
Version 2:
<label class="form-switch">
<input type="checkbox" v-model="showElement"/>
</label>
Check this fiddle: https://jsfiddle.net/x4wykp2u/4/
Hope this makes sense

Nuxt-link delay transition to new page?

This is a follow up to #1458. I'm looking for some direction on how Nuxt expects this to be handled.
I have a menu. When I click on a nuxt-link in the menu, I want to have time to close the menu before the page transition happens. The thing is, I only want that to happen when you click on the nuxt-link in the menu, not every time I go to a certain route (as the previous issue described using a middlewear on the route).
So there are a few different ways to do this, and I'm curious what the "Nuxt" way is?
The way we currently do this, disable the nuxt-link and capture the click, then do a router.push().
<nuxt-link :to="path" event="disabled" #click.native="delayLoad"/>
// Methods
delayLoad(event) {
this.$store.commit("CLOSE_MENU")
setTimeout(()=>{
this.$router.push(event.target.pathname)
}, 2000)
}
Is this a good idea? I just always have an aversion to hijacking nuxt-link and browser navigation like this. It seems janky.
The other ideas we played with were using a query param on the nuxt-link, and then using that in a middlewear to delay the page transition. That seemed worse to me, because now my URL's have a query param in them that is used for an animation, seems like that is abusing query params. This also triggers the page loading progress bar, which isn't really the intent, it's to have a sequenced animation happen, then page load.
It seems to me that perhaps nuxt-link should have a delay prop, or perhaps the page transition config should allow for a delay (like it does with duration)?
I wanted to do this as well and came up with the following solution. Using the new slots api you can more elegantly customise the nuxt-link behaviour:
<nuxt-link v-slot="{ route, href }" :to="path" custom>
<a :href="href" #click.prevent="$emit('navigate', route)">
<slot></slot>
</a>
</nuxt-link>
This will make the link emit a navigate event with the route as a param. You then listen for this event wherever you include your menu component, like this:
<template>
<transition
name="fade"
#after-leave="maybeNavigate"
>
<MainMenu
v-if="menuIsVisible"
#navigate="navigate"
/>
</transition>
</template>
<script>
export default {
data: () => ({
menuIsVisible: false,
navigateToOnMainMenuClose: null,
}),
methods: {
navigate(route) {
this.navigateToOnMainMenuClose = route
this.menuIsVisible = false
},
maybeNavigate() {
if (this.navigateToOnMainMenuClose) {
this.$router.push(this.navigateToOnMainMenuClose)
this.navigateToOnMainMenuClose = null
}
},
},
}
</script>
Whenever you click a nav link in the menu, the route will be stored and the menu will close. After the menu out animation has finished, maybeNavigate() will push the stored route, if there is one. This removes the need for a setTimeout and if you manage to click multiple links in quick succession only the last one will be stored and navigated to.
Since nuxt-link is essentially a wrapped version of vue's router-link, if you look at the documentation for that there is an event property that accepts string or string[], looking at it's source code here: https://github.com/vuejs/vue-router/blob/dev/src/components/link.js#L86
you can see it will register a listener for disabled in this instance. It may make more sense to pass an empty array so that no event listeners are registered, but that's at the cost of readability.
Otherwise, #click.native is the suggested way to handle custom click handlers for router-link (see: https://github.com/vuejs/vue-router/issues/800#issuecomment-254623582).
The only other concerns I can think of are what happens if you click 2 different links in rapid succession and what happens if you click more than once. May just want to add a variable to track if a link has been clicked to prevent firing setTimeout multiple times, which could navigate you from page A to B and then to C as all timeouts will fire if not canceled. Or maybe you want to only navigate to the 'last' link clicked, so if another link is clicked, you would cancel the earlier setTimeout. This is realistically an edge case that probably won't be an issue, but worth exploring.
Otherwise, IMO, looks good to me. This seems like the simplest way to implement this without having to create a custom component / plugin. I'm no expert, but is likely how I would implement this functionality as well. It would be nice to see a delay option though since I can see myself using that functionality as well with vuetify.
Another potential method would be to do your store commit in beforeTransition: https://nuxtjs.org/api/configuration-transition/
Though I'm not sure that there is access to the store there, so you might have to write a custom plugin for that as well. Again, seems more complicated than it's worth for a simple delayed animation. Simple, working code is sometimes the best solution, even if it's not the most extensible option.
See also: How can I transition between two nuxt pages, while first waiting on a child component transition/animation to finish?
for another way of handling this.

DOJO dropdown and datetextbox suddenly stop working after opening/closing dialog form a few times

I'm using dojo 1.9 inside Ibm Content Navigator and my dropdowns(dijit.form.DropDownButton) suddenly stop working after opening and closing the same screen about 15-20x. I click on the arrow and the options are not displayed. That happens with DateTextBox(dijit/form/DateTextBox) as well. And not only my screen dropdowns stop work but every single dropdown and DateTextBox in the system dont work anymore. All the other widgets are working fine. I have to refresh the page to make everything work again. Not doing anything special here.
these are 2 examples of dropdown and datetextbox
Does anyone have a clue of what is happening here ?
<div
data-dojo-attach-point="invoiceDateMisc"
data-dojo-attach-event="onChange: setCAVATCodes"
name="${id}_invoiceDateMisc" id="${id}_invoiceDateMisc"
tabindex="13"
data-dojo-type="dijit/form/DateTextBox"
constraints="{ min: '01/01/1950', max: new Date()}"
missingMessage="Invoice Date is a required field."
rangeMessage="Invoice Date must not be a future date."
required="true" >
</div>
<div data-dojo-attach-point="dbCrMisc"
name="${id}_dbCrMisc"
id="${id}_dbCrMisc"
data-dojo-type="ecm.widget.Select"
tabindex="14" >
</div>
It turned out there were some no modal dialogs where I show error/warning messages to users that were not being properly closed, just hidden, so after some time of system usage, it breaks the dropdowns and calendars for some unknow reason. Really tought one, no error messages, nothing on console, not a clue and I still dont know why it happened. And my attempt to fix this was just a guess, a feeling, knowing a bit more of Dojo behavior.

Change Global Variable onclick/img source update with javascript variable

First off I am completely new to Javascript but I have some HTML/CSS experience. I've been trying to create an html/javascript image gallery for a website; (It would probably be a lot easier to do in PHP but the web coordinator disabled PHP on our server for security reasons).
Anyway What I have is a page showing an Album-list, Album-browser and Photo-viewer in different a div and 2 iframes respectively. I have it set up so that when someone clicks on an album from the album list, a page is opened up in the album browser section (iframe:"browser-frame" showing thumbnails of all the images in the particular album). I've been trying to set it up so that when someone clicks on an image in the album browser the image will appear in the Photo-viewer section (iframe:"viewer-frame" showing the photo itself).
I didn't want the photo's in the viewer-frame to be larger than the set dimensions for the viewer-frame so I created a page for the viewer-frame that puts the image in a div with a class of set dimensions (defined in a stylesheet) as follows:
...<body>
<div class="photoview">
<img id="viewed_image" class="large" src="images/album1/1.jpg" />
</div>
</body>...
I then created a script that updates the image src to a variable:image_to_be_viewed and called it image-changer.js
// JavaScript Document
{
var image_to_be_viewed="images/album1/1.jpg";
document.getElementById("viewed_image").src=image_to_be_viewed;
}
And added a script to the viewer-frame page so it looks like:
...<body>
<div class="photoview">
<img id="viewed_image" class="large" src="images/album1/1.jpg" />
<script src="image-changer.js"></script>
</div>
</body>...
Now I wanted the gallery to work so that in the page loaded in the browser-frame, whenever one clicked on one of the pictures, the value of the global variable 'image_to_be_viewed' would be changed to the source of the clicked image as follows:
<body>
<div class="photobrowse">
<img class="medium" src="images/album1/1.jpg" onClick="image_to_be_viewed='images/album1/1.jpg'"/>
<img class="medium" src="images/album1/2.jpg" onClick="image_to_be_viewed='images/album1/2.jpg'"/>
<img class="medium" src="images/album1/3.jpg" onClick="image_to_be_viewed='images/album1/3.jpg'"/>
</div>
</body>
It doesn't work....
the gallery i'm working on is on http://ptc.tamu.edu/test/gallery_directory/test_gallery.html
everything up to the loading of the selected picture in the viewer frame works (I'm running the onlick event on the default loaded pictures 1,2,3 in the browser-frame page)(default pic's 4 and 5 simply load the image in the iframe but with no way to adjust the size it is too big and gets cut off and i don't want that)
I've been working on for an entire day and I'm sure I'm doing something wrong here but I can't figure out what exactly it is. I have a feeling it has to do with changing the global variable: image_to_be_viewed from the browser-frame page but I wanted to confirm with experts instead of flopping about like a headless fish. I'm going to continue trying to figure this out but i thought maybe having some expert assistance would speed up the process.
What the onclick triggers should be a javascript function call.
e.g. onclick="changeImg('images/album1/1.jpg')"
And the function itself should looks like this
function changeImg (image_to_be_viewed) {
document.getElementById("viewed_image").src = image_to_be_viewed;
}
btw, you probably should learn javascript a little bit more before work on something real. I recommend this book
thank you I got it to work! I figured that the changeImg function was targeting the wrong document/wrong frame and I fixed it by changing the js script to:
function changeImg (image_to_be_viewed) {
window.parent.viewer_frame.document.getElementById("viewed_image").src = image_to_be_viewed;
}

jquery jqmodal .load() issue

I have a modal window using jqmodal. I need a button within that modal to load a different page in the modal. I have this functioning in all browsers except safari.
JS
<script language="javascript">
function shipCalc() {
$('.jqmWindow').load("/ash/shop/shipping.php");
}
</script>
HTML
<form name="form9" id="form9" method="post">
Zip: <input type="text" size="5" name="zip">
<a href="#" id="submitbtn" onclick= "shipCalc();" >zip</a>
</form>
KEEP IN MIND! The class .jqmWindow is a modal window using the jqmodal jquery plugin. It is NOT just a div on a page. I am using the method .load() to change what has been loaded in the modal window after it has popped up. The html shown above is inside the page that is originally loaded in the modal. I am having trouble understanding why this works in all browsers besides safari. I posted earlier and got some responses that weren't quite addressing the real problem here, which is that I can not use the .load() method to load anything into my modal window in safari. (Ive stripped some non-important information regarding future modifications I will make to further make this suite the needs of the site, just to keep this nice and simple to understand...)
function shipCalc() needed to be on both the initial page AND the page that gets loaded into the modal for safari to load everything properly. All other browsers did not require that. All is working now, so I figured I would post my own answer in case anyone was ever searching for something similar!