displaying alert message in angular when move to other tab - javascript

I'm fairly new to Angular and need to solve what seems to be a simple problem: show an alert or confirmation message on navigating between tabs in angular bootstrap. the issue is when moving to another tab, the tab will open first and then show an alert message if clicked on cancel it will back to the previous tab, what I want simply is to not leave the current tab until click on confirmation to leave.
<ul ngbNav #navWithIcons="ngbNav" [(activeId)]="activeTab" class="nav-tabs">
<li ngbNavItem="docs">
<a ngbNavLink (click)="navigateTab('docs')">
<span [data-feather]="'file-text'"></span>Documents</a>
<ng-template ngbNavContent>
<p>
any content
</p>
</ng-template>
</li>
<li ngbNavItem="external">
<a ngbNavLink (click)="navigateTab('external')">
<span [data-feather]="'chrome'"></span> External
Resource</a>
<ng-template ngbNavContent>
<p>
any external link
</p>
</ng-template>
</li>
</ul>
<div [ngbNavOutlet]="navWithIcons" class="mt-2"></div>
TS:
navigateTab(navTab: string) {
if (navTab != this.currentTab) {
if (this.isInputUpdated) {//if there is an update on the current tab inputs then
this.confirmationMessage(true, this.currentTab);
this.isInputUpdated = false;
}
this.currentTab = navTab;
}
}

You can listen to navChange event on the ngbNav element and stop the event from propagating
<ul ngbNav #navWithIcons="ngbNav" [(activeId)]="activeTab" class="nav-tabs" (navChange)="navChanged($event)">
...
</ul>
navChanged(event) {
event.preventDefault()
}
Inside the confirmationMessage method, if clicked on confirm set active tab with the value of currentTab

Related

How to handle event delegation with priorities?

I have this look-a-like code in my app :
let item;
$('.parent').on('click', function () {
item = $(this).attr('item') || 0;
});
$('.parent').on('click', '.children', this, function () {
doSomething();
});
<div class="parent" item="50">
<div class="children">
</div>
</div>
<div class="parent" item="51">
<div class="children">
</div>
</div>
<div class="parent" item="52">
<div class="children">
</div>
</div>
I have a parent element with several children in it. Clicking anywhere on the parent element will give me an item information, so I will be able to load functions according to this item variable on click on children.
My problem is : I have to delegate the onClick event on children to parent element otherwise the events will trigger in this order :
Click on any child
Click on parent, which is too late because I need item variable first
I have a functionality that replaces the parent element if activated, since it was dynamically inserted into the DOM, I have to delegate the onClick event as well, like this :
$('.grandParent').on('click', '.parent', function () {
item = $(this).attr('item') || 0;
});
Now my problem is that the events are triggering in the wrong order again :
Click on any child
Click on parent
How can I manage to set click event on parent as top priority?
Edit :
I will be more specific. I have a messages list on my page, each .message element contains the message content but also some functionnalities like edit, delete, set as favorite, like, etc.
Like this :
<div class="message" data-item="1">
<a class="edit">E</a>
<a class="delete">X</a>
<a class="favorite">Fav</a>
<a class="like">Like</a>
<div class="content">
Hello world !
</div>
</div>
<div class="message" data-item="2">
<a class="edit">E</a>
<a class="delete">X</a>
<a class="favorite">Fav</a>
<a class="like">Like</a>
<div class="content">
Hello world !
</div>
</div>
Each one of those functionnalities will trigger different functions when clicked : edit(), delete(), like(), etc.
All of them will make AJAX requests which will then send the item variable to my server in order to know what item has to be impacted by this click.
To avoid repetition in my events handlers, I am trying to get the data-item attribute's value with one event bound to click on .message element, relying on the bubbling of children elements.
Get the item where you actually want it and get rid of the handler on parent:
$('.parent').on('click', '.children', function () {
item = $(this).closest('.parent').attr('item');
doSomething();
});
EDIT:
Then get the item when you click on the grandparent:
$('.grandParent').on('click', '.children', function () {
item = $(this).closest('.parent').attr('item');
});
EDIT #2:
Based on the OPs updated requirements, do it like this:
<div class="message" data-item="1">
<a class="action edit" data-type="edit">E</a>
<a class="action delete" data-type="delete">X</a>
<a class="action favorite" data-type="favorite">Fav</a>
<a class="like">Like</a>
<div class="content">
Hello world !
</div>
</div>
<div class="message" data-item="2">
<a class="action edit" data-type="edit">E</a>
<a class="action delete" data-type="delete">X</a>
<a class="action favorite" data-type="favorite">Fav</a>
<a class="like">Like</a>
<div class="content">
Hello world !
</div>
</div>
$(document).on('click','.message .action',function(e) {
const item = $(this).closest('message').attr('item');
switch($(this).data('type')) {
case 'edit': doEdit(item); break;
case 'delete': doDelete(item); break;
case 'favorite': doFavorite(item); break;
}
});
See, one event handler?
It's a very common pattern to do what you're doing. In the absence of a more robust framework (e.g. React), then using plain jQuery this is how it should be done.

abort Link redirection in Meteor.js

Hi Guys i have a small problem,
i have a click event on a settings icon but the settings icon is inside a link so when i click the icon the click event is called but i cant see anything because i getting redirected to the next page so i need a way to click the icon without firing the link
<template name="startseite">
<div id="viewport">
{{#each gebiet}}
<div id="viewmode">
this is the link--> <a id="link" href="/straßen/{{this._id}}">
<div id="gebietsCard">
<ul id="gebieteListe">
and here the icon --> <li id="settings"><i id="setting" class="material-icons md-24 md-light">settings</i></li>
<li id="überschrift">{{Gebietsname}}</li>
<li>{{Gebietsnummer}}</li>
<li>{{Ort}}</li>
</ul>
</div>
</a>
</div>
<div id="editmode">
<div id="gebietsCardEdit">
test
</div>
</div>
{{/each}}
</div>
</template>
my js:
Template.startseite.events({
'click #settings': function(){
console.log("geklickt")
$("#editmode").css('display', 'inline');
$("#viewmode").css('display', 'none');
}
});
I hope you can help me thanks Guys ;)
This could be done easily with:
Template.startseite.events({
'click #settings': function(e){
e.stopPropagation();
e.preventDefault(); // I am not sure if this is needed, try it yourself and remove if it is no use
$("#editmode").css('display', 'inline');
$("#viewmode").css('display', 'none');
}
}
You can find more information regarding these two functions here:
https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault

Angular Modal ng-click does not work

I have made a modal in angular, it pops up great but the exit button doesnt fire to close the modal. It works if the button to open is reclicked but adding a new button inside the modal does not fire the function. Btw there is no bootstrap in this.
<section class="modal" ng-show="showMenu">
<div ng-click="setActive(album)">
<p class="exit" ng-click="modalFunc()"><i class="fa fa-times-circle fa-2x" aria-hidden="true"></i></p>
<h1>{{albumMod.artist}} - {{albumMod.title}}</h1>
<ul class="tracks">
<span><img src={{albumMod.img}}></span>
<li>Album: {{albumMod.album}}</li>
<li>Price: $1.29</li>
</ul>
<form style="display: inline" action="/#cart" method="get">
<button ng-click="setActive(album); cartFunc()" id="{{album.id}}"><a>Add</a></button>
</form>
</div>
</section>
$scope.closeMenu=true;
$scope.showMenu=false;
$scope.showItems=false;
$scope.modalFunc= function(){
$scope.showMenu = !$scope.showMenu;
console.log($scope.selected);
$scope.showItems = !$scope.showItems;
$scope.closeMenu=!$scope.closeMenu;
// console.log($scope.selected.attr("id"));
};
$scope.showMenu flag which you have used to hide popup is not used correctly. When $scope.modalFunc method is called then you negate the value of $scope.showMenu and assigned. So after assignment, $scope.showMenu value will be true.
Now you have used ng-show="showMenu" so your popup will not be hide.
Correct code will be:
1. Set $scope.showMenu = true in the callback which called when popup is opened.
2. $scope.modalFunc= function(){
$scope.showMenu = !$scope.showMenu;
...
}
3. Remove $scope.showMenu=false; since it is not needed.

message display/block on button click

I have kept notification button in my header.
When user click Get notified then it should replace by message Notified successfully
CODEPEN: CODEPEN
HTML
<li style="display:none" id="l1">Notified soccessfully ..
</li>
<li><a style="display:block" id="l2" href="#about">Email</a>
</li>
<li>
<div id="input-collection" class="input-group input-group-lg left-input-group">
JS
function notify()
{
alert("hi");
document.getElementById("l2").dispaly='none';
document.getElementById("input-collection").dispaly='none';
document.getElementById("l1").dispaly='block';
}
In codepen, donno what is the issue with my code.
IT should be display not dispaly and you should provide .style
function notify()
{
alert("hi");
document.getElementById("l2").style.display='none'; // Changed
document.getElementById("input-collection").style.display='none'; // Changed
document.getElementById("l1").style.display='block'; // Changed
}
Code Pen

Isolate specific HTML elements with jQuery

OK, what I need may sounds rather complex, but here it is...
Let's say we have the HTML code below (it's still just an example, but it's still quite accurate) :
<div data-role="content" comp-id="jqm-content-6207" id="jqm-content-6207" class="" data-theme="" >
<!-- New Navigation Bar #1 -->
<div data-role="navbar" data-position="fixed" comp-id="jqm-navbar-4603" id="jqm-navbar-4603" class="" data-iconpos="top" >
<ul>
<!-- New Navigation Bar Item #1 -->
<li>
<a href="#" comp-id="jqm-navbar-item-6671" id="jqm-navbar-item-6671" class="" data-icon="home" data-theme="" >
One
</a>
</li>
<!-- / New Navigation Bar Item #1 -->
<!-- New Navigation Bar Item #2 -->
<li>
<a href="#" comp-id="jqm-navbar-item-4404" id="jqm-navbar-item-4404" class="" data-icon="gear" data-theme="" >
Two
</a>
</li>
<!-- / New Navigation Bar Item #2 -->
</ul>
</div>
<!-- / New Navigation Bar #1 -->
<!-- New Navigation Bar #2 -->
<div data-role="navbar" data-position="fixed" comp-id="jqm-navbar-4658" id="jqm-navbar-4658" class="" data-iconpos="top" >
<ul>
<!-- New Navigation Bar Item #2.1 -->
<li>
<a href="#" comp-id="jqm-navbar-item-5321" id="jqm-navbar-item-5321" class="" data-icon="home" data-theme="" >
One
</a>
</li>
<!-- / New Navigation Bar Item #2.1 -->
<!-- New Navigation Bar Item #2.2 -->
<li>
<a href="#" comp-id="jqm-navbar-item-2843" id="jqm-navbar-item-2843" class="" data-icon="gear" data-theme="" >
Two
</a>
</li>
<!-- / New Navigation Bar Item #2.2 -->
</ul>
</div>
</div>
First-off, the core idea is : when the user clicks an item with the comp-id attribute set, then add class msp-selected just to this specific element (and remove it from all other elements).
This is how I'm handling this specific part :
function removeAll()
{
$("*").each(function() {
if ($(this)!==undefined) {
$(this).removeClass("msp-selected");
}
});
}
$(document).ready( function() {
$('[comp-id]').bind('click', function(event) {
removeAll();
$(event.target).addClass('msp-selected');
});
});
So, as you may already have guessed it's like a way of "selecting" item (by clicking on them) from the HTML document.
Now, here's the catch :
How could I make it so that the "selection" is progressive?
What I mean...
When the user first clicks on the Navigation Bar :
Check if the first div with comp-id is selected (has the class msp-selected). If not, select it.
If the first div is already selected, then go one level deeper looking for comp-id, and select that one.
So, any ideas?
How would you do it?
P.S. When one clicks on the <a> of a navigation item, what specific item receives the event?
Is it the <div data-role=\"navbar\"> or the navigation bar item? No matter what, from all these items, I want to select the outermost - not being currently selected. Next time, when the user clicks again and e.g. the navigation bar is selected, then unselect it and select it's child (go deeper).
EDIT :
When trying :
$(document).ready( function() {
$('[comp-id]:not(.msp-selected)').on('click', function(e) {
removeAll();
$(this).addClass('msp-selected');
});
});
What I'm getting when clicking on navbar-item is :
Selected Div : jqm-navbar-item-8421
Selected Div : jqm-navbar-8598
Selected Div : jqm-content-2860
Selected Div : jqm-page-3363
So, basically it just "selects" the outermost container. Which is wrong... Next time the user clicks, the content should selected - then the navbar and then the navbar-item....
You may write a function like that (i am not sure if the syntax is correct)
function onclick(sender)
{
if(type of sender == null )
{
return;
}
if(sender.className=="selected")
{
onclick(sender.childElement[0]);
// OR If you need all children to be selected,
// for( var i =0; i<sender.childElement.count; i++)
// onclick(sender.childElement[i]);
}
else
{
sender.className="selected";
}
}

Categories

Resources