I have an app created with vuetify and i want to hide the main scrollbar when my dialog is open. For example, there is two scrollbar when the dialog is open: https://i.stack.imgur.com/a4xt7.png
I just want to hide the main scrollbar only when the dialog is open. This is what I have tried :
document.body.style.overflow = "hidden";
but it doesn't work.
Here is where the code being implemented :
async mounted() {
this.$store.commit("SET_LOADING", true);
try {
await this.loadData();
if (!this.item) {
this.$showDialog({
title: "Something Wrong",
body: `Member not found!`,
});
this.closePage();
} else {
// here
document.body.style.overflow = "hidden";
await this.$store.dispatch("area/get");
this.role = this.item?.roles[0];
if (
this.item?.user &&
this.$store.state.user?.roles?.find(
(x) => x == this.$roles.Admin
)
)
this.email = this.item?.user.email;
}
} catch (error) {
Promise.reject(error);
} finally {
this.$store.commit("SET_LOADING", false);
}
},
you can set false value scrollable prop for your dialog
Related
I dont know much about vue/bootstrap and reading docs does not help me to understand how it all works.
How to open a modal that is created after the page was loaded. From user input. User clicks button then the modal loads into a list prop and then renders into DOM and then it opens up.
Im at the point where i created event when user clicks the button that loads the modal into the list, but how do you catch the "modal has been added to DOM" event and then you can use getElementByID to instantiate the modal and then use .show() to show it?
I can see that the card that supposed to render on the page loads/renders, but the method get null. Im guessing that the method runs before the page/DOM has been re-rendered. So how do you run another method with parameter of sorts after the custom event that added the item to list has been triggered?
The code is too big and convoluted to post. But if need be i could try to trim it down, but its a mess.
App.vue
<template>
<div class="container-center">
<AnimeList />
</div>
</template>
AnimeList.vue
<template>
<div class="containerlist">
<AnimeCardModal
v-for="anime in animeList"
:anime="anime"
#checkAnimeListForRelatedEvent="checkAnimeListForRelated"
/>
</div>
</template>
<script setup>
import { defineComponent } from "vue";
import AnimeCardModal from "./AnimeCardModal.vue";
import axios from "axios";
</script>
<script>
export default defineComponent({
name: "AnimeList",
data() {
return {
animeList: [],
limit: 30,
page: 1,
reachedEnd: false,
};
},
methods: {
async getAnimeLsit() {
const res = await axios.get("/api", {
params: { page: this.page, limit: this.limit },
});
this.animeList = res.data.data;
this.page = res.data.next.page;
this.limit = res.data.next.limit;
},
async getNextBatch() {
let bottomOfWindow =
document.documentElement.scrollTop + window.innerHeight ===
document.documentElement.offsetHeight;
if (bottomOfWindow && !this.reachedEnd) {
const res = await axios.get("/api", {
params: { page: this.page, limit: this.limit },
});
res.data.data.map((item) => {
this.animeList.push(item);
});
if (!res.data.next) {
this.reachedEnd = true;
} else {
this.page = res.data.next.page;
this.limit = res.data.next.limit;
}
}
},
async checkAnimeListForRelated(animeID) {
if (!this.animeList.filter((anime) => anime.id === animeID).length > 0) {
const res = await axios.get("/api/anime", {
params: { id: animeID },
});
if (res.data.data.length > 0) {
this.animeList.push(res.data.data[0]);
console.log("added to list");
}
}
// Add the anime to the list
},
},
created() {
window.addEventListener("scroll", this.getNextBatch);
},
deactivated() {
window.removeEventListener("scroll", this.getNextBatch);
},
async mounted() {
await this.getAnimeLsit();
},
components: {
AnimeCardModal,
},
});
</script>
Here is the method that gets triggered by the user click event where it loads the Not in main list data and should render on page/DOM.
async checkAnimeListForRelated(animeID) {
if (!this.animeList.filter((anime) => anime.id === animeID).length > 0) {
const res = await axios.get("/api/anime", {
params: { id: animeID },
});
if (res.data.data.length > 0) {
this.animeList.push(res.data.data[0]); <--------------------------------------
console.log("added to list");
}
}
// Add the anime to the list
},
The added item is a modal with element id. I want to instantiate this element as new Modal() and open it with .show().
But the i get error that the element does not exist = null and i cant get it, but i can see it on screen.
EDIT:1
Ok so like as per usual, once i post on SO i find an answer to my problem, but it turns into another problem.
SO to get the rendered element i used this:
async checkAnimeListForRelated(animeID) {
if (!this.animeList.filter((anime) => anime.id === animeID).length > 0) {
const res = await axios.get("/api/anime", {
params: { id: animeID },
});
if (res.data.data.length > 0) {
this.animeList.push(res.data.data[0]);
console.log("added to list");
this.$parent.$nextTick(() => { <----------------------
const myModal = new Modal(
document.getElementById("anime-card-modal-" + animeID)
);
myModal.show();
}
}else{
const myModal = new Modal(
document.getElementById("anime-card-modal-" + animeID)
);
myModal.show();
}
// Add the anime to the list
},
It works, but now the modals overlay each other, seems like its not working like when you add the attributes to the card element that opens modal:
:data-bs-target="'#anime-card-modal-' + anime.id"
data-bs-toggle="modal"
Is there a way to get the same effect from method as with these attributes?
I want to open a modal, by clicking an element with those attributes, then when i click another element with them attributes (different target id) it closes previously opened modal and opens the target modal.
Alright, i found a solution, works pretty good.
Instead of using myModal.show() i used myModal.toggle("anime-card-modal-" + animeID) and the else statement is not needed in the event method:
async checkAnimeListForRelated(animeID) {
if (!this.animeList.filter((anime) => anime.id === animeID).length > 0) {
const res = await axios.get("/api/anime", {
params: { id: animeID },
});
if (res.data.data.length > 0) {
this.animeList.push(res.data.data[0]);
console.log("added to list");
this.$parent.$nextTick(() => {
const myModal = new Modal(
document.getElementById("anime-card-modal-" + animeID)
);
myModal.toggle("anime-card-modal-" + animeID) <---------------
}
}
// Add the anime to the list
},
I have a problem, I can't remove the event listener in the condition inside the callback function.
I have the impression that the syntax is correct. But the event is still active.
Does anyone know how to remove the event touchstart?
mutation.target.removeEventListener("touchstart",(e) => { handleClickButton(e) }, true);
const headerSearchBox = document.querySelector(".search-box");
function handleClickButton(event) {
event.preventDefault();
alert("You Clicked on the button")
}
const mutationCallback = function (mutationList) {
mutationList.forEach((mutation) => {
let isSearchOpen = mutation.target.classList.contains("search-container");
// If Search Bar is Open : Do This...
if (mutation.type === "attributes" && isSearchOpen && mutation.oldValue.includes("open")) {
console.log("Search Bar is Open");
mutation.target.addEventListener("touchstart",(e) => { handleClickButton(e) }, true);
} else {
console.log("Search Bar is Close");
mutation.target.removeEventListener("touchstart",(e) => { handleClickButton(e) }, true);
}
});
};
const observer = new MutationObserver(mutationCallback);
observer.observe(headerSearchBox, {
attributes: true,
attributeOldValue: true,
attributeFilter: ["class"],
});
Thanks for your support
So in a chrome extension.
when the user clicks a button
send a message to background
open a new popup window
in the new window, click on the specific element
I can get most of the way but fail to be able to focus in on the necessary document for the js to get the element ID on.
content.js
user_clicked_btn.addEventListener('click', () => {
chrome.storage.sync.get(['xyz'], (result) => {
if (result.xyz['u'].includes('123') && result.xyz['da'] !== 'cool') {
chrome.runtime.sendMessage(
{
s: 'quick',
}
);
}
});
background.js
chrome.runtime.onMessage.addListener((request) => {
if (request.s === 'quick') {
chrome.windows.create({
url: './options.html', type: "popup", focused: true
},
() => {
let queryOptions = { active: true, currentWindow: true };
chrome.tabs.query(queryOptions, function (tabs) {
tabs[0].document.getElementById("element_of_interest").click()
});
}
);
}
});
the issue could be summarized as, how do I get the "document" of a different tab? (assuming I own the 'different tab')
The solution for my problem was to add message passing the whole way to the element of interest and have it click itself.
The result looks like this and behaves as desired.
content.js
user_clicked_btn.addEventListener('click', () => {
chrome.storage.sync.get(['xyz'], (result) => {
if (result.xyz['u'].includes('123') && result.xyz['da'] !== 'cool') {
chrome.runtime.sendMessage(
{
s: 'quick',
}
);
}
});
background.js
chrome.runtime.onMessage.addListener((request) => {
if (request.s === 'quick') {
chrome.windows.create({
url: './options.html', type: "popup", focused: true
}, () => {
setTimeout(() => {
console.log("send message to options page")
chrome.runtime.sendMessage(
{
s: 'quick_click',
}
);
}, 1000);
});
}
});
in the options.html file, the desired element is a react element, so I was able to add a listener in the componentDidMount function
options/index.js
componentDidMount() {
chrome.runtime.onMessage.addListener((request) => {
if (request.s === 'quick_click') {
this.handleClick()
}
});
}
I am using the onclick function with window.open popup, the popup comes to front with the same button, but after closing it is not opening again
<Button hideLabel aria-label={zxxxx "}
className = {styles.button}
icon = "plus"
color = "danger"
size = "lg"
circle
onClick = {
() => {
if (!this.state.isOpened) {
this.setState({
isOpened: true
})
var mywin = window.open("https://app.mural.co", "MsgWindow", "width=1366,height=768")
mywin.addEventListener("beforeunload", function(e) {
this.setState({
isOpened: true
})
}, false)
this.setState({
windows: mywin
}
this.setState(mywin)
}
else {
const window = this.state.windows;
if (window) {
window.focus();
}
}
}
}/>
There is something wrong in your code. Please refer to the commented line.
if (!this.state.isOpened) {
this.setState({
isOpened: true
})
var mywin = window.open("https://app.mural.co", "MsgWindow", "width=1366,height=768")
mywin.addEventListener("beforeunload", function(e) {
this.setState({
isOpened: true
})
}, false)
this.setState({ // there is no closing parenthesis for this
windows: mywin
}
this.setState(mywin)
}
else {
const window = this.state.windows;
if (window) {
window.focus();
}
}
}
Moreover aria-label={zxxxx "} also is missing something. I would highly recommend a code editor that points out these errors for you.
I am trying to redirect the page from login page.I have one flag that is for checking the cart is empty or not. I can set that flag true or false. I want to redirect the pages after logged depends on the flag and logged or not.I have tried but not working.Please help anyone to find the solution.
login.commponent.ts:
onSubmit() {
this.submitted = true;
if (this.loginForm.invalid) {
return;
}
this.loading = true;
this.authenticationService.login(this.f.username.value, this.f.password.value)
.pipe(first())
.subscribe(
data => {
//if cart is not empty
// if(this.flag==true){
// this.router.navigate(['./billing']);
// }
//if cart is empty
//else{
// this.router.navigate(['./cartempty']);
// }
//this.router.navigate([this.returnUrl]);
},
error => {
this.alertService.error(error);
this.loading = false;
});
}
order.component.ts:
goTOloginbilling(){
//if Not logged
// if(????){
// this.router.navigate(['./login']);
// }
//if cart is not empty
// else if(this.flag==true){
// this.router.navigate(['./billing']);
// }
//if cart is empty
//else if(this.flag==false){
// this.router.navigate(['./cartempty']);
// }
}
Demo: https://stackblitz.com/edit/angular-8-registration-login-example-gnjckr?file=app/order/order.component.ts
Looking your code I saw some problems.
In login.component.ts the variable flag is declared like this:
flag: true
I suppose you wanted write flag: boolean= true;
In the same file, in onSumbit function when you call the login function, after you
have the response you had wrote:
this.router.navigate(['./billing']);
But In app.routing.module.ts the route is:
{ path: '', component: BillingComponent, canActivate: [AuthGuard] },
So you had to write:
this.router.navigate(['']);
So in conclusion:
onSubmit() {
this.submitted = true;
if (this.loginForm.invalid) {
return;
}
this.loading = true;
this.authenticationService
.login(this.f.username.value, this.f.password.value)
.subscribe(
data => {
//if cart is not empty
if (this.flag == true) this.router.navigate([""]);
else {
this.router.navigate(["cartempty"]);
}
},
error => {
this.alertService.error(error);
this.loading = false;
}
);
}
Obviously you can define a route for cartEmpty in app.routing.ts:
{ path: 'cartempty', component: CartemptyComponent },