Adding and Removing Styles to li group using Angular 2 - css

<ul>
<li (click)="AddColor($event)">ONE</li>
<li (click)="AddColor($event)">TWO</li>
<li (click)="AddColor($event)">THREE</li>
</ul>
AddColor(e){
e.srcElement.style.color="blue"
}
I have the above list when i click any one of the li item out of 3, the clicked label color should be changed. when i click another all item colors should be revert back to original and change color of current clicked item.

#Mehdi said, you should not access DOM directly untill there is a need.
Always keep in mind, drive your view with data rather than accessing
DOM directly
I have forked and working snippet https://plnkr.co/edit/fgINMc?p=preview

When using Angular, you don't want to directly manipulate the DOM element. Rather let angular deal with it.
In your example, you can generate your list from an array you declare in the code like so
export class YourClass{
links:any;
activeLink = -1;
//...
constructor(){
this.links = ['ONE','TWO','THREE']
}
//...
}
and then in your template you could have :
<ul>
<li *ngFor="let link of links; let i = index"
(click)="activeLink = i"
[ngClass]="activeLink == i? 'blue' : '' " >
</li>
</ul>
and declare a css class blue :
.blue{
color:blue;
}

Related

Angular2 how to change styles of css classes in typescript?

I am trying to toggle viewing categories of items within a very long list, based on what the user wants to see. I want to toggle viewing everything, just meetings, just events or nothing. (this is a small example I really have about 15 categories)
<ul>
<li class="cal-meeting">meeting title</li>
<li class="cal-event">event title</li>
<!-- … the list goes on with various events and meetings -->
So I have the following checkboxes to toggle the viewable items:
<input type="checkbox" checked (click)="toggleCal('meeting')">
<input type="checkbox" checked (click)="toggleCal('event')">
// checkboxes are initially checked however I will make this dynamic saved in DB for user preference
In my angular component in TypeScript I have the function:
toggleCal(toggle_items) {
if (toggle_items === 'meeting') {
// this.display_meeting is initially set to true in ngOnInit
this.display_meeting = !this.display_meeting;
if ( this.display_meeting ) {
// set class cal-meeting to display: block;
} else {
// set class cal-meeting to display: none;
}
}
// do the same thing if toggle_items === 'event'
}
How do I change the display value of the classes cal-meeting and cal-event in my Typescript? I assume just changing the CSS values of the classes is the best way.
I did try:
document.getElementsByClassName('cal-meeting').style.display = 'none';
But I get an error saying "Property 'style' does not exist on type 'HTMLCollectionOf'"
try to convert your selection as HTMLElement
const element = <HTMLElement> document.getElementsByClassName('cal-meeting')[0];
then use :
element.style.display = 'none';
also you can use *ngif for remove it but if you want to use javascript's function to change style you should convert it to HTMLElement
but you can use angular [ngStyle]="{'property': expression}" for changing style like :
<li class="cal-meeting" [ngStyle]="{'display': !this.display_meeting ? 'none': 'block'}">meeting title</li>
or you can add class for example if you have class like :
.d-none: {display: none}
.d-block: {display: block}
you can use it in typescript like:
export class MyComponent implements OnInit {
hidingClass: string = '';
toggleCal(toggle_items) {
if (toggle_items === 'meeting') {
this.display_meeting = !this.display_meeting;
if ( this.display_meeting ) {
this.hidingClass = 'd-block'
} else {
this.hidingClass = 'd-none'
}
}
// do the same thing if toggle_items === 'event'
}
just use it in your html element:
<li class="cal-meeting" [ngClass]="hidingClass">meeting title</li>
If it's just toggle the view, why you did not put something simple like this
<li class="cal-meeting" *ngIf="this.display_meeting">meeting title</li>

StencilJS check if named slot is empty

I have a stencilJS component with two named slots. Is there a way to determine if the slots have been assigned values? For instance, the code snippet below show named slots for "logo" and "menu." How can I check inside the component if both named slots are not empty? Ideally I want to check from inside the component and during componentWillMount() . Thank you.
<koi-menu breakpoint="768" userToggled="false">
<div class="logo__header " slot="logo"><img src="assets/images/logo.png" /></div>
<ul class="nav__wrapper list mw8-ns center-m" slot="menu">
<li class="nav__listitem"><a class="ttu nav__link" href="???">Why Live Grit</a></li>
<li class="nav__listitem"><a class="ttu nav__link" href="???">Clients</a></li>
<li class="nav__listitem"><a class="ttu nav__link" href="???">Our Programs</a></li>
<li class="nav__listitem"><a class="ttu nav__link" href="???">Our Story</a></li>
</ul>
</koi-menu>
The use of a slot can be detected from the host element in the componentWillLoad() function:
hasLogoSlot: boolean;
hasMenuSlot: boolean;
#Element() hostElement: HTMLStencilElement;
componentWillLoad() {
this.hasLogoSlot = !!this.hostElement.querySelector('[slot="logo"]');
this.hasMenuSlot = !!this.hostElement.querySelector('[slot="menu"]');
}
This might not apply to your problem, but if you only want to style the slotted elements—say only add margins on non-empty slots—you can use the ::slotted pseudo-element:
::slotted([slot="logo"]) {
/* Apply styles to non-empty logo */
}
::slotted([slot="menu"]) {
/* Apply styles to non-empty menu */
}

Applying CSS class conditionally in Angular2

I have below HTML code which recursively create list items based on list returned from Component and I want to apply 'first-child' CSS class to first List item only.
<ul class="link-list-horz">
<li *ngFor="let menu of menulist" [ngClass]="first-child:">
{{menu}}
</li>
</ul>
.first-child a
{
border-radius: 10;
}
export class AppComponent {
name = 'Quiz';
menulist = ['Home','AngularQuiz'] ;
useremailid = 'Gaurav-Gupta';
}
Please suggest. I am totally new to Angular2.
ngClass needs a condition to know whether to set that class on the element. You can use the built-in index that comes with ngFor for that.
Try this:
<li *ngFor="let menu of menulist; let i=index" [ngClass]="{'first-child': i === 0}">

Is it possible to make anchor tag <a> without href attr look like with href attr?

I've made dropdown using angular-ui-bootstrap
public/partials/partial2.html
<ul ...
<li class="dropdown" dropdown>
<a href="admin/partial2" role="button" class="dropdown-toggle" dropdown-toggle> brand list </a>
<ul class="dropdown-menu" role="menu">
<li>.....
</ul>
obviously href="admin/partial2" route(by angular-route) to same partial page( so same entire page ) and do nothing
but I need hand emoticon when user put mouse-over the anchor
Can I have this effect without specifying "href" attribute?
Yes, use css for that, create a rule for your anchor class (dropdown-toggle) in this case as follows:
.dropdown-toggle:hover {
cursor: pointer;
}
you can use <a> without href, but it's just like a spam inside your script.
For example, you have a text inside the div or, say, span, as in:
<span>Sitemap</span>
or, you have <ul> <li> in your dropdown menu, then you can add NEW Selector in your stylesheet(or CSS).
for example:
.mymenu li {
cursor:pointer;
}
From the code, I can explain that, you just need cursor:pointer, to make it happen. that's all.
if you set the cursor inside li, all li's will have that pointer.
to make it specific, I mean, if you need the pointer for only one scope, say, menu or dropdown menu where li or ul is used, you can add new selector then.

AngularJs translation directive stop working when I change div class using jquery

Well, being straight forward the problem is my $scope.$apply() is also not digesting the changes to rerun the translate directive.
I show you the HTML with applied translation directive and jQUERY code to change the class on resize of the windows (client).
HTML for menu:
<div id="navigation" ng-cloak>
<div class="container-fluid">
BRAND NAME
<ul class='main-nav'>
<li ng-class="{'active':activeLink == 'home'}">
<a href="#/">
<span>Home</span>
</a>
</li>
<li ng-class="{'active':activeLink == 'planning'}" data-trigger="hover">
<a href="#" data-toggle="dropdown" class='dropdown-toggle'>
<span>Planning</span>
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<a href="#" data-toggle="dropdown" class='dropdown-toggle'>Goals</a>
<ul class="dropdown-menu">
<li>
{{'TOP_MENU.GOAL_LIST' | translate}}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
HERE is the JQuery Code to make it responsive for screen size changes.
function checkLeftNav() {
var $w = $(window),
$content = $("#content"),
$left = $("#left");
if ($w.width() <= 840) {
if (!$left.hasClass("mobile-show")) {
$left.hide();
$("#main").css("margin-left", 0);
}
if ($(".toggle-mobile").length == 0) {
$("#navigation .user").after('<i class="fa fa-bars"></i>');
}
if ($(".mobile-nav").length == 0) {
createSubNav();
}
} else {
if (!$left.is(":visible") && !$left.hasClass("forced-hide") && !$("#content").hasClass("nav-hidden")) {
$left.show();
$("#main").css("margin-left", $left.width());
}
$(".toggle-mobile").remove();
$(".mobile-nav").removeClass("open");
if ($content.hasClass("forced-fixed")) {
$content.removeClass("nav-fixed");
$("#navigation").removeClass("navbar-fixed-top");
}
if ($w.width() < 1200) {
if ($("#navigation .container").length > 0) {
versionFluid();
$('body').addClass("forced-fluid");
}
} else {
if ($('body').hasClass("forced-fluid")) {
versionFixed();
}
}
}
}
Now What my solution was to get he nav element scope on which the jquery is applying class and call the $apply() on its scope. which is not working.
Solution Code:
$(window).resize(function(e) {
checkLeftNav();
// get the scope of element and apply $apply()
var sc = angular.element('.mobile-nav').scope();
sc.$apply();
});
But still when ever the screen size is changed to mobile view less than 840 I can see direct code values instead of translated text in menu like this. and When I change back to screen width more than 840 it shows correct translated text. I am experimenting this on chrome on my pc by resizing. I checked on mobile its not translating there too.
AngularJS provides two-way data binding, not two way everything binding. It's not intended to be used this way. $apply() only looks at the data model - it is the function you call when you want to say "Hey, Angular, I've updated the data model, come have a look!" That is literally its only purpose. There is no method in Angular designed to look at the DOM itself for changes - that's very inefficient and against Angular's philosophies anyway, which is why it ships without jQuery.
You might want to evaluate other frameworks that better support this kind of thing. However, if you really wish to do this you can easily convert it into a proper AngularJS module. The best way is to simply paste all of this code into a controller, and then change the window resize binding to use Angular's $window service, like:
var windowElement = angular.element($window);
windowElement.bind('resize', function() {
// Do my calculations here.
});
With your calculations would you compute the same variables but you would store them in scope variables and then adjust your template to use them. For example, what you're doing with $(".toggle-mobile").remove(); could be replaced by:
if (windowElement.width > 840) {
// Other code here
$scope.isMobile = false;
} else {
$scope.isMobile = false;
}
and in your template:
<i class="fa fa-bars"></i>
Give it a whirl, play with it for a week or two, and you'll never go back to jQuery. It takes a lot of getting used to, but once you do you realize how broken the whole "I'm looking at my template and have no idea what mystery event handlers are bound to all this stuff" concept was to begin with.

Resources