Issue
I am trying to use a modal as a prompt for the user to input their search term and search for recipes with a specific ingredient, which I do successfuly, as it is simple redirection. But after redirecting to search, the overlay stays on the page, disabling any clicking or scrolling and only goes away when I refresh the page. What can I do to resolve this? We are using Angular on this project so all of my code for this is in home.component.html and .ts
these are my .ts and .html. There is more to the .ts code but this is all that is relevant. I have tried rewriting the code to be more Angular friendly, asking friends for help and even AI, but to no avail. Since I am very new to this, I might not be noticing something that could seem clear to you, so please be kind. Thank you in advance.
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css'],
})
export class HomeComponent implements OnInit, OnDestroy {
searchTerm: string = '';
private readonly imagesToShowInLandscape = ['bowl', 'paella', 'hotpot', 'omelette', 'brownChunks', 'tomYum', 'fish', 'raznjici', 'chickenThigh'];
private readonly imagesToHideInPortrait = ['omelette', 'chickenThigh', 'tomYum'];
constructor(private el: ElementRef, private renderer: Renderer2, private router: Router) {}
ngOnInit() {
const openModalButtons = document.querySelectorAll('a[data-bs-target]');
const closeModalButtons = document.querySelectorAll('[data-bs-dismiss="modal"]');
const overlay = document.getElementById('overlay');
openModalButtons.forEach((button) => {
button.addEventListener('click', (event) => {
event.preventDefault(); // Prevent default navigation
const modalId = (button as HTMLElement).dataset['bsTarget'];
this.openModal(modalId);
});
});
closeModalButtons.forEach((button) => {
button.addEventListener('click', () => {
const modal = (button as HTMLElement).closest('.modal');
this.closeModal(modal);
});
});
overlay?.addEventListener('click', () => {
const modals = document.querySelectorAll('.modal.show');
modals.forEach((modal) => {
this.closeModal(modal);
});
});
this.adjustImageVisibility();
window.addEventListener('resize', this.adjustImageVisibility);
}
ngOnDestroy() {
window.removeEventListener('resize', this.adjustImageVisibility);
}
search() {
this.redirectToRecipes(this.searchTerm);
}
redirectToRecipes(searchTerm: string) {
this.router.navigate(['/recipes'], { queryParams: { search: searchTerm } });
}
openModal(modalId: string | undefined) {
if (modalId) {
$(`#${modalId}`).modal('show');
}
}
closeModal(modal: Element | null) {
if (modal) {
$(modal).modal('hide');
}
}
<!--<link rel="stylesheet" href="../../../../assets/styles/style.css"/>-->
<div class="row d-flex justify-content-center mt-5">
<!-- Kuham Button -->
<div class="col-md-6 d-flex justify-content-center justify-content-md-end">
<div class="card bg-transparent border-0">
<div class="card-body d-flex justify-content-center" data-bs-toggle="modal" data-bs-target="#modal1">
<a class="izberi">
<span class="button-text">Kuham</span>
<img src="assets/images/cooking-icon.png" alt="Button Image" id="choice-images" />
</a>
</div>
</div>
</div>
<!-- Jem Button -->
<div class="col-md-6 d-flex justify-content-center justify-content-md-start">
<div class="card bg-transparent border-0">
<div class="card-body d-flex justify-content-center" data-bs-toggle="modal" data-bs-target="#modal2">
<a class="izberi">
<span class="button-text">Jem</span>
<img src="assets/images/eating-icon2.png" alt="Button Image" id="choice-images" />
</a>
</div>
</div>
</div>
</div>
<div class="modal" id="modal">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Recipe title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
recipe
</div>
</div>
</div>
</div>
<div class="modal" id="modal1" #modal1>
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Kaj kuhaš?</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form (ngSubmit)="search()">
<div class="mb-3">
<input class="form-control" type="text" [(ngModel)]="searchTerm" name="searchTerm" placeholder="Vpiši ime jedi ali sestavine">
</div>
<button type="submit" class="btn btn-primary">Poišči</button>
</form>
</div>
</div>
</div>
</div>
<div class="modal" id="modal2" #modal2>
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Kaj bi jedel?</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form>
<div class="mb-3">
<label for="exampleInput" class="form-label"></label>
<input class="form-control" type="text" placeholder="Vpiši ime jedi ali sestavine" aria-label="default input example">
</div>
<button type="submit" class="btn btn-primary">Poišči</button>
</form>
</div>
</div>
</div>
</div>
All of my previous "fixes" actually did not do anything. When I tried the Angular friendly version, I couldn't even get it to open, and none of my alterations managed to get rid of the overlay. They either get rid of everything or nothing at all.
Solution
You can simply make the submit button dismiss the modal by adding data-bs-dismiss="modal"
, and remove all the code related to BS modal.
<button type="submit" class="btn btn-primary" data-bs-dismiss="modal">Poišči</button>
and move data-bs-toggle
to the link, to make it trigger the modal:
<a class="izberi" data-bs-toggle="modal" data-bs-target="#modal1">
<span class="button-text">Kuham</span>
and let Bootstrap data attributes handle modals completely.
Also, using jQuery and DOM methods with Angular is discouraged, instead, use ViewChild
to manipulate template's HTML, for example, reference modal template variable in the component, and then instantiate it with Bootstrap in ngAfterViewInit
:
@ViewChild('modal1') modal1El!: ElementRef;
modal1!:any;
ngAfterViewInit() {
this.modal1 = new bootstrap.Modal(this.modal1El.nativeElement);
}
and then you could close/open it depending on the workflow:
redirectToRecipes(searchTerm: string) {
this.modal1?.hide();
this.router.navigate(['/recipes'], { queryParams: { search: searchTerm } });
}
see: How to perform DOM manipulation in Angular components?
Answered By - traynor
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.