I'm facing a strange error in my Angular 4 HTML Template, I'm trying to toggle the class of <i> tag, but only one class shows up, but not the other. Here is my code;
<i [ngClass]="{'fa fa-eye': visible, 'fa fa-eye-slash': !visible}" aria-hidden="true" (click) = "toggle(pass)"></i>
TS:
visible = false;
toggle(event){
this.visible = !this.visible;
}
When i check my app, the first icon shows up i.e. the default on fa fa-eye-slash but when i click on it it shows only box.
Edit:
Tried with different icons from FA, but nothing shows up.
You need to change the html to:
<i class="fa" [ngClass]="{'fa-eye': visible, 'fa-eye-slash': !visible}" aria-hidden="true" (click) = "toggle(pass)"></i>
Related
Hi every one I have created stackblitz https://stackblitz.com/edit/angular-fnvhnn-giypgb?file=app%2Fexpansion-overview-example.html for reference, I have used expansion panel to exapand the content, based on click the element the expansion happening in the stackblitz, for example if we click All element on top the all content will gets exapand, if we click B element the B content will gets expand.
What I exactly looking is I want to use ngstyle or ngclass in top loop of {{tab}}, if we click All tag it should be change into green color and again if click same All tag it's should change into red color, if we click B tag it should be change into green color again if click same B tag it's should change into red color like toggle.
if panelstate = false the tag should be in red color and if it is true it's need to change green color
panel open state:-
panelOpenState = false;
Top ngfor loop;-
<div style="display: flex;justify-content: space-evenly;">
<div *ngFor="let tab of getTablist();"> <p (click)='clickOntab(tab)' [ngStyle]="{'color':panelOpenState === 'true' ? 'green' : 'red' }">{{tab}}</p></div>
</div>
Ts File
panelOpenState = false;
public tabType: string = "";
clickOntab(tab) {
if (this.tabType != "" && this.tabType === tab) {
this.panelOpenState = false;
this.tabType = "";
} else {
this.panelOpenState = true;
this.tabType = tab;
}
}
getTablist() {
const tabList = this.cricketList.map(list => list.alphabet);
return ["All"].concat(tabList);
}
}
You can achieve this by using ngClass like shown below,
[ngClass]="(panelOpenState===true)?'greenClass':'redClass'"
As of now ngClass of all tabs are binded to single property panelOpenState, so all are changing colors altogether but you should store the open or closed state of each tab separately in some array. Such that only the tab i.e opened is green in color and vice-versa.
Refer this working example demo
I think the best readable soultion would be this:
<div style="display: flex;justify-content: space-evenly;">
<div *ngFor="let tab of getTablist();">
<p (click)='clickOntab(tab)' [class.redClass]="!panelOpenState" [class.greenClass]="panelOpenState">
{{tab}}
</p>
</div>
</div>
Working StackBlitz
A simple approach to add an array with the tabs name
tab = ["ALL", "A", "B", "C"];
panelOpenState = "";
and make panelOpenState to store the open tab name.
Secondly update the template file as follows:
<div style="display: flex;justify-content: space-evenly;">
<div *ngFor="let tab of getTablist();">
<p (click)='clickOntab(tab)'
[ngStyle]="{'color':panelOpenState === tab ? 'green' : 'red' }">{{tab}}</p>
</div>
ngStyle will trigger when the tab name is equal to the panelOpenState and this will do the trick.
I am using angular material tab library to display vertical and horizontal tabs. There are 3 horizontal tabs and in 2nd horizontal tab, there are vertical tabs. When I put Next button it should go to next horizontal tab. It's working with 1st horizontal tab but in 2nd horizontal tab Next button is not appearing.
Here is: stackblitz - ngular-material-tabs-inside-tab
in tab-group-basic-example.html in 2nd horizontal tab, I put Next button:
<div class="m-10">
<button (click)="nextTab(2)">Next</button>
</div>
in ts file:
nextTab(index: number): void {
this.selectedIndex = index;
}
Looks like the issue is that you want do display something outside of mat-tab. Moving the next button inside it does the trick:
<mat-tab *ngFor="let tab of tabs; let index = index" [label]="tab">
<div class="m-10" #appenHere></div>
Contents for {{tab}} tab <br> <br>
<button (click)="addNewComponent()">
Append to {{tab}}
</button>
<div class="m-10">
<button (click)="nextTab(2)">Next</button>
</div>
</mat-tab>
I have a Material Tab component in Angular 2.
I want to have a button at the end of the tabs, that acts as a add tab button. Upon clicking on it a new tab is created before it.
I tried putting a button there, but couldn't find how to place it exactly next to the last tab.
So what I did is I added a tab that acts like a button. When this tab is clicked, a new tab is created.
However, when this tab is clicked, it gains focus. While I can change which tab is selected, the tab still has the focused UI (it is colored).
How can I make it lose it's focus completely?
P.S. If there is a way to add a regular button next to the last tab, without making it a tab, this would also be good.
Edit - Code:
This is how my tabs are setup:
<mat-tab-group (selectedTabChange)="selectedTab($event)">
<mat-tab>
<ng-template mat-tab-label>
Basic Details
</ng-template>
</mat-tab>
<mat-tab #categoryTab *ngFor="let table of mCase.Tables; let tableIndex = index" [attr.data-index]="tableIndex">
<mat-tab>
<mat-tab #addCategory>
<ng-template mat-tab-label>
<div color="white" class="center">Add category</div>
</ng-template>
</mat-tab>
</mat-tab-group>
Code behind:
public selectedTab(e) {
if (e.index == 1 + this.mCase.Tables.length) {
//Add new category
this.CreateTable();
this.selectedIndex = this.mCase.Tables.length;
}
Promise.resolve().then(() => this.selectedIndex = e.index);
}
You could try add the button like this:
<mat-tab-group>
<mat-tab>
<ng-template mat-tab-label>
Basic Details
</ng-template>
</mat-tab>
<mat-tab disabled>
<ng-template mat-tab-label>
<button mat-icon-button (click)="foo()">
<mat-icon>add_circle</mat-icon>
</button>
</ng-template>
</mat-tab>
</mat-tab-group>
Working example: https://stackblitz.com/edit/angular-zrklwg
By the way, if you are bothered by the button having disabled like styles, you can just override that with some custom CSS! :D
You can use .blur() on the event.currentTarget of the button which has been clicked. .blur() is the opposite of the .focus() method and will remove focus from an element.
In you question you said:
Upon clicking on it a new tab is created before it.
You didn't add any html, so I just went and created an example of how you can dynamically append buttons to the html via a data bound array.
this.buttons.splice(clickedButtonIndex, 0, {Name: "New Button"});
To learn about how this works, see this answer.
This is the crux of the component code that you can use to blur focus on the element.
addButton(clickedButtonIndex, event){
this.buttons.splice(clickedButtonIndex, 0, {Name: "New Button"});
event.currentTarget.blur();
}
Working Example: https://stackblitz.com/edit/angular-vslscm
In the example, I have set a red background in css to be applied to buttons when they are focused. You can see that when you click on a button, it momentarily will turn red before being toggled off again. Clicking the buttons will add a new button before the button which was clicked.
I have an anglarJS project that has a horizontal navigation bar. Each element in the navigation bar is a category and uses an angularJS dropdown directive to show the subcategories for that category.
I would like the drop down to fill the whole screen from left to right. Currently the drop down determines it's width from the css "min-width" property. This does not solve my desire for the drop down menu to fill the whole screen I have seen some websites do this, and was wondering if there is a way to force my dropdown to fill the whole screen from left to right.
Here is the html for the page/drop down including the css that specifies the dropdown width.
Here is a picture of the dropdown again. I added blue arrows to indicate what I mean when I want the drop down to fill the whole screen.
The pictures are pretty high resolution and show you all the details. The page is rather complex to try and replicated in a plunker.
The whole thing needs to be responsive as well, and is based off of Bootstrap 3 and AngularJS Bootstrap.
Thanks for any help you can give!
David
I found a solution for the problem.
I created a button group that floats left that is on the same row as the button group in the center. The button group that floats left only contains one button, and that button has it's visibility set to hidden.
You have the dropdown attached to this button, rather than the ones in the center, since the dropdown won't start any farther left than the beginning of the button it is attached to.
<div class="pull-left">
<div class="btn-group" dropdown is-open="isOpen">
<button type="button" style="visibility: hidden" class="btn btn-link dropdown-toggle filter-criteria-variety-category-name" dropdown-toggle ng-disabled="disabled">
<span class="caret"></span>
</button>
<div class="dropdown-menu top-level-category-drop-down-standard" ng-style="{{windowWidth}}" ng-click="$event.stopPropagation()" >
<div ng-click="$event.stopPropagation()" ng-mouseleave="close()" ng-mouseenter="keepOpen()">
<div ng-if="currentCategory != undefined">
<horizontal-menu-inner close-drop-down-menu=$parent.closeDropDownMenu top-level-category=$parent.currentCategory></horizontal-menu-inner>
</div>
</div>
</div>
</div>
</div>
And for the centered button group that contains your categories you want to trigger the dropdown you pass the 'ioOpen' variable into the centered button directive as an attribute.
<div class="text-center">
<div class="btn-group">
<div class="horizontal-top-level-category" ng-repeat="topLevelCategory in categoryNavigationGraph">
<horizontal-top-level-category is-open=$parent.isOpen current-category-id=$parent.currentCategoryId top-level-category=topLevelCategory></horizontal-top-level-category>
</div>
</div>
</div>
You then have that directive set up to close or open the drop down depending on whether the mouse enters or leaves the button in that directive
<button ng-mousemove="activeMenuItemm()" ng-mouseleave="close($event)" ng-mouseenter="open()" type="button" ng-class="{'filter-criteria-variety-category-name-hover': filterCriteriaCategoryActive}" class="btn btn-link dropdown-toggle filter-criteria-variety-category-name" ng-disabled="disabled">
{{topLevelCategory.text}}
The tricky part is not having the dropdown close when you hover down from the centered button onto the dropdown
I did this by figuring out if the mouse was leaving from "down", which should not close the dropdown, or other, which should from the last position, which was calculated In the centered button directive link function:
link: function (scope, element) {
init();
scopeLevelFunctions();
function init(){
calculateBoundry();
}
function scopeLevelFunctions(){
scope.calculateElementBoundry = function(){
calculateBoundry();
}
}
function calculateBoundry(){
var boundry = element[0].getBoundingClientRect();
scope.boundry = boundry;
scope.topBoundry = boundry.top;
scope.bottomBoundry = boundry.bottom;
scope.leftBoundry = boundry.left;
scope.rightBoundry = boundry.right;
}
},
The open function triggered by mouseenter sets the boundry, which the close calculates from that value to see if this is a mouseleave that is leaving down
$scope.open = function(){
$scope.calculateElementBoundry();
$scope.currentCategoryId = $scope.topLevelCategory.categoryId;
$scope.filterCriteriaCategoryActive = true;
$scope.timeoutPromise = $timeout(function() {
$scope.isOpen = true;
}, 150);
};
$scope.close = function($event){
$scope.lastPosition = {
x : $event.clientX,
y : $event.clientY
};
var deltaX = $scope.lastPosition.x - $event.clientX,
deltaY = $scope.lastPosition.y - $event.clientY;
if($event.clientY >= ($scope.bottomBoundry - 8))
$scope.direction = "bottom";
else
$scope.direction = "other";
if($scope.direction != "bottom"){
if($scope.timeoutPromise != undefined)
$timeout.cancel(this.timeoutPromise);
$scope.isOpen = false;
$scope.filterCriteriaCategoryActive = false;
}
else{
if($scope.isOpen == false && $scope.timeoutPromise != undefined){
$timeout.cancel(this.timeoutPromise);
$scope.filterCriteriaCategoryActive = false;
}
}
I put the timeout in there so that if the user is just scrolling to bottom of the screen the drop down does not just appear. I cancel the timeout if they mouseleave and the drop down is not open.
The dropdown gets different data in it because the centered category directive has an attribute "categoryId" that is shared with the directive that the dropdown is located in. As that categoryId is changed that directive determines what that new categories submenu should be and feeds that into the dropdown.
I know how wide the dropdown should be because in the directive that contains the dropdown/invisible button I calculated the window width:
var width = $window.innerWidth;
$scope.windowWidth = "{'min-width':" + width + "}";
and on the dropdown I use ng-style to set this width
ng-style="{{windowWidth}}"
I want to relocate my bootstrap popover in the left side, i.e. I want to move the whole popover in the left side, while the white arrow would stay in one place.
I would like to have the effect which is on google.com website, when you click blue icon you see popover but its content is relocated while the white arrow is located under the user.
I know that I can use something like this:
.popover {
top:0 !important;
margin-top:10px;
}
Unfortunately, it relocates the whole popover altogether with white arrow.
What I have now (popover is on the right side and there's no place between screen edge and my popover)
What I want to have (small distance between popover and monitor's edge):
“I want to change the position of content of this popover so that this
arrow will be placed further on the left„
When the popover is shown the arrow position is calculated in Tooltip.prototype.replaceArrow based on width/height and placement. You can force a specific position with this CSS :
.popover .arrow {
left: 90px !important; /* or 45% etc */
}
But that will affect all popovers. Popovers is injected and removed to and from the DOM, and there is by default no way to target visible popovers individually. If you want to style the arrow on a specific popover, a workaround is to hook into the shown.bs.popover event, detect which popover that is being shown, and style the arrow for that popover if needed. Example :
.on('shown.bs.popover', function() {
var $popover = $('.popover')[0];
switch ($(this).attr('id')) {
case 'a' : $popover.find('.arrow').css('left', '10px');break;
case 'b' : $popover.find('.arrow').css('left', '40%');break;
case 'c' : $popover.find('.arrow').css('left', '180px');break;
default : break;
}
})
To get this to work, there must be only one popover shown at a time (see fiddle). It can be worked out with multiple visible popovers also, but then we need to add some HTML to the popover content.
see demo -> http://jsfiddle.net/uteatyyz/
As what I have understood so far, you want to achieve the popover to the left of the button.
Please check this Plunker Link
HTML Code:
<div class="pull-right">
<button type="button" mypopover data-placement="left" title="title">Click here</button>
</div>
Angular Code:
var options = {
content: popOverContent,
placement: "bottom",
html: true,
date: scope.date,
trigger: 'focus'
};
I have edited the answer as per the images that you have shown.
If this is not is answer, then please comment below.
Regards D.