How can I switch the stylesheets based on the button click in an AngularJS 2.0 application?
As right now I am including stylesheets on the head section of index.html page.
#Component({
selector: ...,
template: ...,
styles: [`
:host(:not(.some-class)) {
border: solid 1px red;
}
:host(.some-class) {
border: solid 3px green;
}
`
]})
export class MyComponent {
#HostBinding('class.some-class') isSomeClass = true;
}
Plunker example
I would leverage the ngStyle directive:
<h1 [ngStyle]="{'font-style': style, 'font-size': size, 'font-weight': weight}">
Change style of this text!
</h1>
<div (click)="changeStyle()">Update style</div>
Updading the style, size values from a method (linked to a click event) will update your style:
export class SomeComponent {
style = 'normal';
weight = 'normal';
size = '20px';
changeStyle($event: any) {
this.style = 'italic';
}
Related
Working on a react/typescript project, I have a div and want to replace the border color and width of a div when it's clicked:
<div
className="showroom-card "
onClick={() => setSelection({ showroom: 'Westchester' })}
>
I know it should be simple but I'm pretty new to this.
in javascript you can make but please describe more
div.style.border="1px solid #000";
With pure html/js it would be look like that:
.showroom-card {
width: 500px;
height: 300px;
background-color: yellow;
border: 2px solid red;
}
.selected {
border: 2px solid black;
}
<div
id="card1"
class="showroom-card"
onClick="(function(divId) {
targetDiv = document.querySelector(`#${divId}`)
targetDiv.classList.toggle('selected')
})('card1');return false;"
></div>
But in react you must use state of component to manipulate div's style. For example, you would use divToggled variable in state of your component to render border and manipulate its color. The handler function, named handleDivClick change state and component will be rerendered:
class YourComponent extends React.Component {
...
handleDivClick = () => {
this.setState(divToggled: !this.state.divToggled)
}
...
render() {
return (
<div
onClick={this.handleDivClick}
className={`showroom-card ${this.state.divToggled ? 'selected' : ''}`}
/>
)
}
}
I'm creating a commenting function for a text editor in a Vue.js project. The commenting function will highlight a portion of text and put a comment card on the right side, similar to Google comment system in docs.
As I was working on the highlight function of the feature I realized that the setAttribute class only worked on a global class and not scoped for the component the text is displayed in. Why is this? What is the functionality behind this? I'm curious about how it works under the hood.
tl;dr element.setAttribute('class', 'classname') on a dynamically created element (document.createElement('element')) does not work if the class is in scoped styles, why?
<template>
<div>
<p #click="highlight">
{{ text }}
</p>
</div>
</template>
<script>
export default {
name: 'Paper',
data() {
return {
text: "Some lorem ipsum"
}
},
methods: {
highlight() {
var selected = window.getSelection().getRangeAt(0)
var selectedText = selected.extractContents()
console.log(selected)
console.log(selectedText)
var span = document.createElement("span")
console.log(span)
span.setAttribute('class', 'highlight-text')
span.appendChild(selectedText)
selected.insertNode(span)
}
}
}
</script>
<style scoped>
div {
box-shadow: rgba(60, 64, 67, 0.15) 0px 1px 3px 1px;
height: 1123px;
width: 794px;
padding: 96px;
margin: 100px
}
p {
line-height: 1.4;
}
</style>
<style>
.highlight-text {
background-color: yellow;
}
</style>
Also, if you have any tips on how I can improve the code it is very much appreciated!
Vue will replace the scoped css class name with a unique data attributes and set this on the element.
I.e the setAttribute tries to add a class name which actually does not exists.
Example from docs:
https://vue-loader.vuejs.org/guide/scoped-css.html#mixing-local-and-global-styles
I want to bind the height of one angular component to the height of a div. I am trying to use template reference to fetch the height.
Is it possible to do so using this method in a clean way? I want to do it something like this in snippet below.
<div [style.height.px]="section1.offsetHeight"></div>
<app-custom-tag #section1>
</app-custom-tag>
I want the height of <div> to be equal to height of <app-custom-tag>
I can't use css column layout for this as these two elements are not positioned together.
I think there are a few extra things you'll have to do.
When you reference a component inside the view, you'll get the class instance. With that in mind, you can inject the ElementRef so you can get information about the native element.
Consider this example:
foo.component.ts
#Component({
selector: 'foo',
template: `foo`,
styles: [`:host { color: red; display: block; height: 300px; } `]
})
export class FooComp {
get offsetHeight () {
return this.el.nativeElement.offsetHeight;
}
constructor (private el: ElementRef) { }
}
app.component.ts
#Component({
selector: 'my-app',
template: `
<foo #f></foo>
{{ f.offsetHeight }}
<br>
<div style="border: 1px solid black" [style.height.px]="f.offsetHeight"></div>
<!-- <div style="border: 1px solid black" [ngStyle]="{ height: f.offsetHeight + 'px' }"></div> -->
<br>
<input #i id="demo" type="text">
{{ i.id }}
`,
})
export class AppComponent { }
When you reference a DOM element in the view, you'll get that DOM element.
ng-run demo.
The standard glyph icons are pretty boring
https://www.w3schools.com/bootstrap/bootstrap_ref_comp_glyphs.asp
The following code works, but instead of a filled in star with black, is there a way to make it some other color, e.g., orange?
In addition, is there a more interesting set of icons for download to use for buttons?
const glyphStarEmpty = 'glyphicon glyphicon-star-empty';
const glyphStarFull = 'glyphicon glyphicon-star';
class Checkbox extends React.Component {
constructor(props) {
super(props);
this.state = {
checked: false,
currentGlyph: glyphStarEmpty
};
this.toggleChecked = this.toggleChecked.bind(this);
}
toggleChecked() {
if(this.state.currentGlyph == glyphStarEmpty){
this.setState({
currentGlyph : glyphStarFull
})
}
else{
this.setState({
currentGlyph : glyphStarEmpty
})
}
this.setState({
checked: !this.state.checked
});
}
render() {
return (
<button className={this.state.currentGlyph} onClick={this.toggleChecked}></button>
);
}
}
You can do that with simple css
<span class="icon-some"></span>
.icon-some {
color: orange;
}
Wow, why so complicated? Just add some CSS inside the <head> tag:
<style type="text/css">
.glyphicon { color: orange; }
</style>
Another icons that you can use are from font awesome.They have tons of button icons and i'm sure you'll like it,i've used this icons for a lot of websites,to change the colors simply ad some css as other members told you before me
You could use an inline style:
<button style={{ color: 'orange' }} className={this.state.currentGlyph} onClick={this.toggleChecked}></button>
If you want a black outline in addition, try this:
<button style={{ color: 'orange', textShadow: '0 0 1px black' }} className={this.state.currentGlyph} onClick={this.toggleChecked}></button>
You could add a css color property like this:
HTML
<span class="orange glyphicon glyphicon-envelope"></span>
CSS
.orange {color: orange;}
With the help from surrounding answers, the solution became obvious. This is not perfect since I want a black border with a pure white inside (or maybe even the way stackoverflow color scheme using gray for the up/down triangles) for unchecked state for maximum contrast, but I will fix that on my own:
render() {
if(!this.state.checked)
{
return (
<button className={glyphStarFull} onClick={this.toggleChecked}></button>
);
}
else
{
return (
<button style={{ color: 'orange', textShadow: '0 0 1px black' }} className={this.state.currentGlyph} onClick={this.toggleChecked}></button>
I have two components: BuilderComponent and InputTextComponent.
With drag and drop I put a directive in the sortableList element of the BuilderComponent template. With the inspector I can see the directive appears in the sortablelist DOM element:
<div class="row">
<div class="col-md-12">
<ul id="sortableList">
<zbjfb-input-text></zbjfb-input-text>
</ul>
</div>
How can I force the BuilderComponent to detect that the content of the template is changed since the last compile and then re-render the template with the new added directive so I can see the new compiled InputTextComponent.
BuilderComponent:
import { Component } from '#angular/core';
#Component({
selector: 'zbjfb-builder',
template: '
<div class="row">
<div class="col-md-12">
<ul id="sortableList">
</ul>
</div>
</div>
'
})
export class BuilderComponent {}
InputTextComponent:
import { Component } from '#angular/core';
#Component({
selector: 'zbjfb-input-text',
templateUrl: './input-text.component.html',
styleUrls: ['./input-text.component.css']
})
export class InputTextComponent {}
Any idea?
Thanks in advance.
If your drag'n'drop solution is HTML5 based, maybe you can make use of HostListener decorator from '#angular/core' to hack your drag and drop exchange logic:
Add something like this on your drop area component:
#HostListener('drop', ['$event'])
onDrop(event: any) {
//do something
}
And something like this on your draggable component:
#HostListener('dragstart', ['$event'])
onDrag(event: any) {
//do something
}
HostListeners provide you ways to implement conventional listeners for element events like onmousedown, onkeyup, ondrop, ondrag.
Then think of some logic to identifiy what's being dragged/dropped and change the drag area component model. Here's some functional code I've made inspired by W3Schools topic on drag'n'drop:
import { Component, HostListener, Input } from '#angular/core';
// The draggable component
#Component({
selector: 'dragme',
template: `
<div draggable="true">
Drag {{name}}!
</div>
`,
styles: [`
[draggable] {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
-khtml-user-drag: element;
-webkit-user-drag: element;
background-color: #AAA;
border: 1px solid black;
padding: 24px;
margin: 12px;
}
`]
})
export class DragMe {
#Input()
name:string = "";
#HostListener('dragstart', ['$event'])
onDrag(event:any){
event.dataTransfer.setData("name",this.name);
}
}
// The drop area component
#Component({
selector: 'drop',
template: `
<div class="drop">
Drop over me!
<ul>
<li *ngFor="let i of items">{{i}}</li>
</ul>
</div>
`,
styles: [`
.drop{
border: 1px solid black;
padding: 24px;
}
`]
})
export class DropOverMe {
items:string[] = [];
#HostListener('dragover', ['$event'])
onDragover(event:any){
event.preventDefault();
}
#HostListener('drop', ['$event'])
onDrop(event:any){
event.preventDefault();
var name = event.dataTransfer.getData("name");
this.items.push(name);
}
}
// The functional example
#Component({
selector: "drag-example",
template: `
<dragme name="Bob"></dragme>
<dragme name="Alice"></dragme>
<dragme name="Carl"></dragme>
<drop></drop>
`
})
export class DragExample{
}
Full code at: https://github.com/rafaelodon/angular2-html5-dragndrop-example