how to change ngx bootstrap backdrop modal when two modals are open - angular5

ngx-bootstrap for angular with bootstrap 4 version you see the below code when we open one popup the backdrop is working fine when we open another popup(modal) from the first modal the backdrop opacity is not reflecting on the first popup. The opacity is not changing how to change the opacity(backdrop) of first modal when second modal is open.
import { Component, TemplateRef } from '#angular/core';
import { BsModalService } from 'ngx-bootstrap/modal';
import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
#Component({
selector: 'demo-modal-service-nested',
templateUrl: './service-nested.html'
})
export class DemoModalServiceNestedComponent {
modalRef: BsModalRef;
modalRef2: BsModalRef;
constructor(private modalService: BsModalService) {}
openModal(template: TemplateRef<any>) {
this.modalRef = this.modalService.show(template, { class: 'modal-lg' });
}
openModal2(template: TemplateRef<any>) {
this.modalRef2 = this.modalService.show(template, { class: 'second' });
}
closeFirstModal() {
this.modalRef.hide();
this.modalRef = null;
}
}
<button type="button" class="btn btn-primary" (click)="openModal(template)">Open first modal</button>
<ng-template #template>
<div class="modal-header">
<h4 class="modal-title pull-left">First modal</h4>
<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef.hide()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
This is a first modal
<button type="button" class="btn btn-primary" (click)="openModal2(templateNested)">Open second modal</button>
</div>
</ng-template>
<ng-template #templateNested>
<div class="modal-header">
<h4 class="modal-title pull-left">Second modal</h4>
<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef2.hide()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
This is nested modal.<br>
<button *ngIf="modalRef" type="button" class="btn btn-danger" (click)="closeFirstModal()">Close first modal</button>
</div>
</ng-template>

I need to show 2 overlapping modals, the second is smaller than the first and I just can't hide the first. My solution was to apply a background-color to the second one:
openModal2(template: TemplateRef<any>) {
this.modalRef2 = this.modalService.show(template, { class: 'second' });
document.getElementsByClassName('second')[0].parentElement.style.backgroundColor = 'rgba(0, 0, 0, 0.4)';
}
document.getElementsByClassName('second')[0].parentElement.style.backgroundColor
= 'rgba(0, 0, 0, 0.4)';

I have found a CSS workround for nested modal backdrop issue.
.modal {
background: rgba(0, 0, 0, .3);
}

Related

Vue js slider with left and right

export default {
name: 'MovieSlider',
data() {
return {
index: 0,
imgs: [
'https://7themes.su/_ph/40/303277371.jpg',
'https://7themes.su/_ph/23/730607462.jpg',
'https://7themes.su/_ph/23/730607462.jpg',
],
};
},
computed: {
sideSlide() {
return {
transform: `translateX(${-this.index * 100}vw)`,
};
},
},
methods: {},
left() {
this.index++;
if (this.index > this.imgs.length - 1) {
this.index = 0;
}
this.sideSlide;
},
right() {
this.index--;
if (this.index < 0) {
this.index = this.imgs.length - 1;
}
this.sideSlide;
},
};
<template>
<div class="carusel">
<div class="image-container imgs">
<button class="left buttons" #click="left">
<i class="fa-solid fa-angle-left"></i>
</button>
<div v-for="item in imgs" :key="item.id" :style="sideSlide">
<img :src="item" />
</div>
<button class="right buttons" #click="right">
<i class="fa-solid fa-chevron-right"></i>
</button>
</div>
<div class="popular_films">
<div class="content">
<p class="film_name">Film Name</p>
<p class="film_info">
<i class="fa-solid fa-star"></i>
<span>FIlm vote</span>
<span>Film time</span>
<span>Film year</span>
</p>
<span class="play_treiler"
>Trailer<i class="fa-solid fa-play"></i
></span>
</div>
</div>
</div>
</template>
Hi friends, I want to make slider with vue but something is going wrong, after pressing right or left i want to give a style(size) to image that slides to another image but something is going wrong, in here you can find all of the code that i used in this component, Thank you.

Vue's reactivity not triggered when using Bootstrap 5's alert div

Vue's reactivity not triggered when using Bootstrap 5's alert div.
See my code:
<template>
<div>
<div
v-if="alertICDMsg!==''"
id="alertICDCode"
class="alert alert-info alert-dismissible fade show"
role="alert"
>
<i class="fa-solid fa-lightbulb" />
<strong> Note!</strong> <span v-html="alertICDMsg" />
<button
type="button"
class="btn-close"
data-bs-dismiss="alert"
aria-label="Close"
/>
</div>
<div class="input-group mb-3">
<div class="col-xs-1">
<input
id="ICDCode"
v-model="editing_icdCode"
class="form-control"
placeholder="ICD Code"
aria-label="ICD Code"
#input="ICDCodeSearchRequested"
>
</div>
<input
id="Diagnosis"
v-model="editing_diagnosis"
type="text"
class="form-control"
placeholder="Diagnosis"
aria-label="Diagnosis"
aria-describedby="basic-addon1"
list="icdsearchlist"
#change="SelectedDiagnosisTextOption"
#input="ICDTextSearchRequested"
>
<datalist id="icdsearchlist">
<option
v-for="(disease_option, index) in icd_diagnosis_options"
:key="index"
>
{{ disease_option }}
</option>
</datalist>
<button
id="btnAddDiagnoses"
href="#"
class="btn btn-primary mx-1"
#click="AddDiagnosis"
>
<i class="fal fa-plus-circle" />
</button>
<button
id="btnCopyPreviousDiagnoses"
href="#"
class="btn btn-primary BtnSaveGroup mx-1"
>
<i class="far fa-history" />
</button>
<button
id="quickbill"
class="btn btn-primary mx-1"
>
<i class="fas fa-search-plus" />
</button>
<button
id="clearICD"
class="btn btn-danger mx-1"
#click="ClearICDFields"
>
<i class="fad fa-times-circle" />
</button>
</div>
</div>
<template>
<script>
export default {
data() {
return {
alertICDMsg:"",
};
},
watch: {
alertICDMsg: {
handler(val) {
console.log(`Val for alertICDMsg changed to :${val}`);
},
immediate: true,
deep: true,
},
},
methods: {
ICDCodeSearchRequested() {
console.log(`Search by ICD code`);
this.alertICDMsg="Searching in ICD Code box will search only by code. To search by a diagnosis name, type in the Diagnosis box."
console.log(`alertICDMsg is ${this.alertICDMsg}`);
setTimeout(function() {
console.log(`Dismissing alert`);
this.alertICDMsg='';
console.log(`alertICDMsg is ${this.alertICDMsg}`);
}, 5000);
},
},
}
</script>
Console log:
Search by ICD code
SubClinicalBlock.vue?d801:291 alertICDMsg is Searching in ICD Code box will search only by code. To search by a diagnosis name, type in the Diagnosis box.
SubClinicalBlock.vue?d801:220 Val for alertICDMsg changed to :Searching in ICD Code box will search only by code. To search by a diagnosis name, type in the Diagnosis box.
SubClinicalBlock.vue?d801:293 Dismissing alert
SubClinicalBlock.vue?d801:298 alertICDMsg is
The problem is that after 5 seconds, though the value of the variable changes, the alert is still visible.
I checked some similiar questions, and have seen this happening when bootstrap's javascript wasnt loaded. But for me, Bootstrap v5.0.1 JS is being loaded from the CDN and appears in the sources tab in Chrome.
Try to change the function inside of setTimeout to arrow function like this
setTimeout(() => { // code here })
The this inside of setTimeout(function () => {}) reference to the wrong context (the function itself) instead of the Vue component.
The arrow function doesn't have the this binding so when you use the arrow function the this keyword will reference the Vue component and change the state.
More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

boostrap vue modal not hide when click ok button with validation

I want to add validation to a modal window, I need a behavior in which when the OK button (form submission) is clicked, validation would take place, and if the result is negative, the window should not close
my modal
<b-modal
size="lg"
id="modalToRepair"
title="Add Problem"
title-class="font-18"
centered
body-class="p-4"
no-close-on-backdrop
no-close-on-esc
#ok="onClickModalRepair"
>
<div class="row">
<div class="col-lg-12">
<div class="form-group row">
<label class="col-4 col-form-label">
Repair Problem
<span class="text-danger">*</span>
</label>
<div class="col-8">
<input
v-model="theProblem"
type="text"
class="form-control"
placeholder="Input problem"
name="theProblem"
:class="{
'is-invalid': typesubmit && $v.theProblem.$error
}"
/>
<div
v-if="typesubmit && $v.theProblem.$error"
class="invalid-feedback"
>
<span v-if="!$v.theProblem.required">Requred field.</span>
</div>
</div>
</div>
</div>
</div>
</b-modal>
and my methods
Vue.js
methods: {
onClickModalRepair() {
this.typesubmit = true;
this.$v.$touch();
if (this.$v.$invalid) {
this.$bvModal.show("modalToRepair"); // not work - modal hide
//code for not hide this modal
return;
}
}
},
validations: {
theProblem: {
required
}
}
is it possible?
The method used in the #ok event, is passed an event, which you can call .preventDefault() on, if you want to prevent the modal from closing.
onClickModalRepair(bvModalEvt) {
this.typesubmit = true;
this.$v.$touch();
if (this.$v.$invalid) {
bvModalEvt.preventDefault();
return;
}
}
You can see an example of this on the docs.

Cannot read property 'focus' of undefined in VUE When setting focus to button

I am new to vue I have component which if the endpoint fails, calls my generic 'Error' modal. All this is working fine but I keep getting the following error:
Cannot read property 'focus' of undefined
This only happens for the else part of my method function.
For this specific issue is I my 'failedPrcess' equals any of the following, this is when I get is, all others are fine:
existOrderSearchProdOrders
stockSearchStockLevels
cartFetchCouriers
Code
<template>
<div class="modal fade danger-modal" id="errorModal" tabindex="-1" role="dialog" aria-labelledby="errorModalTitle" aria-hidden="true"
data-keyboard="false" data-backdrop="static" style="z-index: 99999">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content danger-modal-content">
<div class="modal-header danger-modal-headerfooter">An error has occurred</div>
<div class="modal-body">
<p v-if="failedProcess === 'appGetAccount' || failedProcess === 'existOrderSearchProdOrders' || failedProcess === 'stockSearchStockLevels'
|| failedProcess === 'cartFetchCouriers'">
{{ contactTxt | capitalize }}
</p>
<p v-else-if="errorCount < 3">If the error continues, {{ contactTxt }}</p>
<p v-else>As the error has continued, {{ contactTxt }}</p>
<p>
<b>
01234 567890
<br />
Open from 00:00 to 07:00
</b>
</p>
<p>Advising of what you were doing when the error occurred.</p>
</div>
<div class="modal-footer danger-modal-headerfooter">
<a v-if="failedProcess === 'appGetAccount'" ref="logoutButton" class="btn btn-primary" :class="logoutButtClicked" #click="logoutClicked = true" href="/site/logout">
<span v-if="!logoutClicked" id="logoutButtonLabel">Logout</span>
<span v-else id="logoutSpinner">
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
Logging out
</span>
</a>
<router-link v-else-if="failedProcess === 'fetchOrderReportDetails'" to="/review" tag="button"
ref="existOrdersButton" class="btn btn-primary" type="button" data-dismiss="modal" #click.native="closeButton">
Return to existing orders
</router-link>
<button v-else-if="errorCount < 3 && (failedProcess !== 'productsFetchProducts' && failedProcess !== 'existOrderSearchProdOrders'
&& failedProcess !== 'stockSearchStockLevels' && failedProcess !== 'cartFetchCouriers')" ref="closeButton" class="btn btn-primary"
type="button" data-dismiss="modal" #click="closeButton">
Close
</button>
<router-link v-else to="/" tag="button" ref="homeButton" class="btn btn-primary" type="button" data-dismiss="modal" #click="closeButton">
Return to homepage
</router-link>
</div>
</div>
</div>
</div>
</template>
<script>
import * as params from '../params';
export default {
name: "ErrorModal",
data() {
return {
contactTxt: 'please contact us on:',
errorCount: 0,
failedProcess: '',
}
},
mounted() {
VueEvent.$on('show-error-modal', (failedProcess) => {
if (this.failedProcess !== failedProcess) {
this.errorCount = 0;
}
this.failedProcess = failedProcess;
$('#errorModal').modal('show').on('shown.bs.modal', this.focus);
});
},
methods: {
focus() {
if (this.failedProcess === 'appGetAccount') {
this.$refs.logoutButton.focus();
} else if (this.failedProcess === 'fetchOrderReportDetails') {
this.$refs.existOrdersButton.$el.focus();
} else if (this.errorCount < 3 && this.failedProcess !== 'productsFetchProducts') {
this.$refs.closeButton.focus();
} else {
this.$refs.homeButton.$el.focus();
}
},
}
}
</script>`enter code here`
I've tried using v-if before and I also had similar problems and the best solution I found was, instead of using v-if/v-else-if/v-else, use v-show instead to perform conditional rendering.
Also, as the Vue.js doc says:
Generally speaking, v-if has higher toggle costs while v-show has higher initial render costs. So prefer v-show if you need to toggle something very often, and prefer v-if if the condition is unlikely to change at runtime.

Adding directives to simplify ngx-bootstrap modal

This is a suggestion to simplify the basic usages of ngx-bootstrap modal.
The idea is to use 2 directives:
bsDismissModal
replaces bootstrap data-dismiss="modal" attribute
works with "OK" button too, delaying the modal closing to pre-handle button click event
[bsToggleModal]="modalTemplate"
replaces both bootstrap data-toggle="modal" and data-target="#exampleModal" attributes
takes the ng-template reference as input value
Usage example:
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" [bsToggleModal]="exampleModal">
Launch demo modal
</button>
<!-- Modal -->
<ng-template #exampleModal>
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" bsDismissModal>×</button>
<h5 class="modal-title">Modal title</h5>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" bsDismissModal>Cancel</button>
<button type="button" class="btn btn-primary" (bsDismissModal)="save($event)">Save</button>
</div>
</div>
</div>
</div>
</ng-template>
A simple approach would be to use the BsModalService:
DismissModalDirective
import { Directive, EventEmitter, HostListener,
Inject, Output } from '#angular/core';
import { DOCUMENT } from '#angular/common';
import { BsModalService } from 'ngx-bootstrap/modal';
#Directive({
selector: '[dapDismissModal]'
})
export class DismissModalDirective {
// tslint:disable-next-line:no-output-rename
#Output('dapDismissModal') modalClosed = new EventEmitter<MouseEvent>();
private get modalsCount() {
return this.modalService.getModalsCount();
}
constructor(
private readonly modalService: BsModalService,
#Inject(DOCUMENT) private readonly document: Document
) {}
#HostListener('click', ['$event'])
hideModal(click: MouseEvent) {
this.modalClosed.emit(click);
if (click.defaultPrevented) {
return;
}
this.modalService.hide(this.modalsCount);
// Fix BsModalService
if (this.modalsCount === 0) {
this.document.body.classList.remove('modal-open');
}
}
}
(dismissModal)="handleClick($event)" replaces (click)="handleClick($event)", $event being the click MouseEvent.
Modal closing can be cancelled when preventing the click: event.preventDefault();.
ToggleModalDirective
import { Directive, HostListener, Input, TemplateRef } from '#angular/core';
import { BsModalService, ModalOptions } from 'ngx-bootstrap/modal';
#Directive({
selector: '[bsToggleModal]'
})
export class ToggleModalDirective {
// tslint:disable-next-line:no-input-rename
#Input('bsToggleModal') content: TemplateRef<any>;
#Input() bsModalConfig: ModalOptions;
constructor(private readonly modalService: BsModalService) {}
#HostListener('click')
showModal() {
this.modalService.show(this.content, this.bsModalConfig);
}
}