Drop-down list with bullets - javascript

I want to create a drop-down list with bullets using Angular 2 and JavaScript & CSS. I created a drop-down list but i couldn't able to create bullets in list.
This can't be achieved by jQuery, Bootstrap. Any suggestions?
Here is my Code.
dropdownList.component.ts
import { Component} from '#angular/core';
import{FormsModule } from '#angular/forms';
import {Option} from './option';
#Component({
selector: 'app-dropdown',
templateUrl: './dropdown.component.html',
styleUrls: ['./dropdown.component.css']
})
export class DropdownComponent {
selectedItem:Option= new Option(1,'../../assets/blue2.png','option1');
options= [
new Option(1,'../../assets/blue2.png','option1'),
new Option(2,'option2'),
new Option(3,'option3'),
new Option(4,'option4')
];
// OPtion.ts
export class Option{
constructor(public id?: number, public img?:string, public name?:
string )
{
}
}
// component.html:
<select class="dropdown" id="style">
<option *ngFor="let Option of options" value={{Option.id}}
class="dropdownList">{{Option.name}}{{Option.img}}
</option>
</select>

CSS can make anything looked like other stuff. I implement a really simple dropdown but only really basic features. To complete this dropdown you still need to implement ngModel and label/value dropdown items. But I think this have what you descibed already.
import { Component } from '#angular/core'
#Component({
selector: 'demo-dropdown',
template: `
<div class="ui-dropdown">
<label class="ui-dropdown-label">{{selectedItem}}</label>
<span class="ui-dropdown-button" (click)="showList = !showList">﹀</span>
<ul class="ui-dropdown-list" [class.active]="showList">
<li *ngFor="let item of items" (click)="onItemSelected($event)">{{item}}</li>
</ul>
</div>
`,
styles: [`
*{
box-sizing: border-box;
}
.ui-dropdown{
background: #fff;
border: 1px solid black;
border-radius: 3px;
display: inline-flex;
flex-wrap: wrap;
padding: 0;
user-select: none;
width: 250px;
}
.ui-dropdown-label{
flex: 1 1 0;
padding: 0.2em 0.5em;
}
.ui-dropdown-button{
border-left: 1px solid black;
cursor: pointer;
flex: 0 0 20px;
padding-top: 0.2em 0.2;
}
.ui-dropdown-list{
background: #fff;
border: 1px solid black;
border-radius: 3px;
display: none;
flex: 0 0 100%;
margin: 0;
margin-top: 25px;
padding: 0;
position: absolute;
width: 250px;
}
.ui-dropdown-list.active{
display: block;
}
.ui-dropdown-list>li{
cursor: pointer;
list-style: none;
}
.ui-dropdown-list>li::before{
content: '.';
}
.ui-dropdown-list>li:hover{
background: #eee;
}
`]
})
export class DemoDropdown{
showList:boolean = false;
selectedItem:string = null;
items: OptionItem[] = ["option 1","option 2"];
constructor() { }
onItemSelected(e){
this.selectedItem = e.target.innerText;
this.showList = false;
}
}

Related

How do I make an element scroll to the center of the scroll bar upon entering the page

I am making an Angular project which has a "timeline" component, which has a overflow-x: scroll element:
.container {
width: 30vw;
height: 100vh;
background-color: aquamarine;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
}
.timeline-box {
width: 90%;
position: relative;
}
.timeline-strip {
background-color: yellow;
height: 200px;
display: flex;
overflow-x: scroll;
}
.timeline-box:before {
content: '';
position: absolute;
top: 50%;
border-top: 2px solid black;
width: 100%;
height: 0px;
}
.point {
margin: 0 40px;
align-self:center;
}
.point:before {
content: '';
position: relative;
left: 50%;
border-left: 2px solid black;
top: 20px;
}
<div class="container">
<div class="timeline-box">
<div class="timeline-strip">
<div class="point">1</div>
<div class="point">2</div>
<div class="point">3</div>
<div class="point">4</div>
<div class="point">5</div>
<div class="point">6</div>
<div class="point">7</div>
<div class="point">8</div>
<div class="point">9</div>
<div class="point">10</div>
</div>
</div>
</div>
I want the scroll bar of the .timeline-strip element (not the scrollbar of the page itself) to automatically be in the middle when the user enters the page. How can I achieve this? (I am Using Angular if that helps)
You can do this by by taking the scrollWidth property minus the clientWidth property and divide the result of this by 2. This will be the scroll position halfway so you can set this value to the scrollLeft property.
If your div contains images then you want to do this on the window load event. On the document DOMContentLoaded event the images are not loaded yet (unless cashed) and therefore the size of your div may change when the images will be loaded.
//Can be document.addEventListener('DOMContentLoaded', () => {}) when you don't care about images and stuff
window.addEventListener('load', () => {
let scrollElement = document.querySelector('.timeline-strip');
scrollElement.scrollLeft = (scrollElement.scrollWidth - scrollElement.clientWidth ) / 2;
});
.container {
width: 30vw;
height: 100vh;
background-color: aquamarine;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
}
.timeline-box {
width: 90%;
position: relative;
}
.timeline-strip {
background-color: yellow;
height: 200px;
display: flex;
overflow-x: scroll;
}
.timeline-box:before {
content: '';
position: absolute;
top: 50%;
border-top: 2px solid black;
width: 100%;
height: 0px;
}
.point {
margin: 0 40px;
align-self:center;
}
.point:before {
content: '';
position: relative;
left: 50%;
border-left: 2px solid black;
top: 20px;
}
<div class="container">
<div class="timeline-box">
<div class="timeline-strip">
<div class="point">1</div>
<div class="point">2</div>
<div class="point">3</div>
<div class="point">4</div>
<div class="point">5</div>
<div class="point">6</div>
<div class="point">7</div>
<div class="point">8</div>
<div class="point">9</div>
<div class="point">10</div>
</div>
</div>
</div>
personally I do not like to use addEventListener, so #ViewChild is better. This depends which angular is used
modify the answer from #ng-hobby:
add a id to the timeline strip div:
<div class="timeline-strip" #timelineStrip >
modify the viewChild and rename if you want:
#ViewChild('timelineStrip', {static: false}) timelineStripRef: ElementRef;
you can use scrollTo on the timelineStripRef element or timeline-strip:
const width = this.timelineStripRef.nativeElement.clientWidth;
this.timelineStripRef.nativeElement.scrollTo(width/2, 0);
I created a sample for you here on Stackblitz
So, Try something like this using #viewChild & ngAfterViewInit with window.scrollTo():
app.component.html
<hello name="{{ name }}"></hello>
<p class="img" #getHeight>
Start editing to see some magic happen :)
</p>
app.component.ts
import { Component, VERSION, ElementRef, AfterViewInit, ViewChild } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements AfterViewInit {
name = 'Angular ' + VERSION.major;
#ViewChild('getHeight', {static: false}) getHeight: ElementRef;
constructor(private el: ElementRef){}
ngAfterViewInit() {
let pageheight = this.getHeight.nativeElement.offsetHeight;
console.log(pageheight/2)
window.scrollTo(0, pageheight/2);
}
}

I am calling an event listener on a button and it wont create the html element in my DOM

I have some <li> tags under a <ul> in my HTML code. These <li> are
styled with CSS to create cards with a title and description.
I have created a button with an event listener that I wish to create a
new <li> element under the <ul> tag in the HTML when I press the
button.
I retrieve the <ul> and attempt to appendChild() with a new <li>.
This is all within a class in JS. I am not sure why the new <li> cards are not being displayed when I press the button.
```
class DOMHelper {
static clearEventListeners(element) {
const clonedElement = element.cloneNode(true);
element.replaceWith(clonedElement);
return clonedElement;
}
//receives element ID and a New destination in the DOM and sends the
//card to that destination Via Append.
static moveElement(elementId, newDestinationSelector) {
const element = document.getElementById(elementId);
const destinationElement =
document.querySelector(newDestinationSelector);
destinationElement.append(element);
}
}
class Tooltip {}
class ProjectItem {
constructor(id, updateProjectListsFunction, type) {
this.id = id;
this.updateProjectListsHandler = updateProjectListsFunction;
this.connectMoreInfoButton();
this.connectSwitchButton(type);
}
connectMoreInfoButton() {}
//retreives the button of the given DOM element and adds an event
//listener to it that executes updateProjectListHandler
//recieves from: update () {}
//runs updateProjectListsHandler --> this.switchProject -->
connectSwitchButton(type) {
const projectItemElement = document.getElementById(this.id);
let switchBtn = projectItemElement.querySelector('button:last-of-
type');
switchBtn = DOMHelper.clearEventListeners(switchBtn);
switchBtn.textContent = type === 'active' ? 'Finish' : 'Activate';
switchBtn.addEventListener(
'click',
this.updateProjectListsHandler.bind(null, this.id)
);
}
update(updateProjectListsFn, type) {
this.updateProjectListsHandler = updateProjectListsFn;
this.connectSwitchButton(type);
}
}
class ProjectList {
projects = [];
constructor(type) {
//selects all of the li elements under the `#${type}-projects DOM
//element depending on the element input type
//and creates a new ProjectItem for every li element it found.
this.type = type;
const prjItems = document.querySelectorAll(`#${type}-projects
li`);
for (const prjItem of prjItems) {
this.projects.push(
new ProjectItem(prjItem.id, this.switchProject.bind(this),
this.type)
);
}
//new DayOfWeek('Monday');
console.log(this.projects);
}
setSwitchHandlerFunction(switchHandlerFunction) {
this.switchHandler = switchHandlerFunction;
}
//pushes project to the projects array. Project input is "new
//ProjectList('finished');"
addProject(project) {
this.projects.push(project);
DOMHelper.moveElement(project.id, `#${this.type}-projects ul`);
project.update(this.switchProject.bind(this), this.type);
}
//finds every project id in projects with the id matching constant
//projectId
//filters out every dom object with id that does not equal the
//projected input to the function
switchProject(projectId) {
// const projectIndex = this.projects.findIndex(p => p.id ===
projectId);
// this.projects.splice(projectIndex, 1);
this.switchHandler(this.projects.find(p => p.id === projectId));
this.projects = this.projects.filter(p => p.id !== projectId);
console.log('Testing this button')
}
switchDayHandler() {
const selectDayOfWeek = document.getElementById('p4');
//const dayOfWeek = selectDayOfWeek.querySelector('li')
selectDayOfWeek.addEventListener(
'click',
this.updateDayInfoHandler()
);
console.log(selectDayOfWeek);
}
updateDayInfoHandler () {
console.log('TEST TEST TEST');
}
}
class DayOfWeek {
projectList = {
monday: [
{
title: 'test',
description: "test"
}
]
}
constructor(day) {
this.createNewButton;
switch (day) {
case ( 'Monday' ):
//this.addNewListItemHandler();
break;
case ( 'Tuesday' ):
console.log('Tuesday');
break;
case ( 'Wednesday' ):
console.log('Wednesday');
break;
case ( 'Thursday' ):
console.log('Thursday');
break;
case ( 'Friday' ):
console.log('Friday');
break;
//default:
// ingredient = null;
}
}
addNewListItemHandler() {
const projectItem = document.getElementById('active');
const newListItem = document.createElement('li');
newListItem.innerHTML = `id="p2"
data-extra-info="Not really a business topic but still
important."
class="card"
>
<h2>MONDAY ITEM</h2>
<p>Don't forget to pick up groceries today.</p>
<button class="alt">More Info</button>
<button>Finish</button>
`;
projectItem.appendChild(newListItem);
}
createNewButton() {
const newButton = document.getElementById('addButton');
newButton.addEventListener( 'click', this.addNewListItemHandler);
}
}
class App {
static init() {
const activeProjectsList = new ProjectList('active');
const finishedProjectsList = new ProjectList('finished');
activeProjectsList.setSwitchHandlerFunction(
finishedProjectsList.addProject.bind(finishedProjectsList)
);
finishedProjectsList.setSwitchHandlerFunction(
activeProjectsList.addProject.bind(activeProjectsList)
);
}
}
App.init();
```
<body>
<header id="main-header">
<h1>Project Planner</h1>
</header>
<div>
<section id="days-projects">
<header>
<h2>Days</h2>
</header>
<ul>
<li
id="p4"
data-extra-info="Super important conference! Fictional but
still!"
class="card"
>
<h2>Monday</h2>
</li>
<li
id="p5"
data-extra-info="Super important conference! Fictional but
still!"
class="card"
>
<h2>Tuesday</h2>
</li>
<li
id="p6"
data-extra-info="Super important conference! Fictional but
still!"
class="card"
>
<h2>Wednesday</h2>
</li>
<li
id="p7"
data-extra-info="Super important conference! Fictional but
still!"
class="card"
>
<h2>Thursday</h2>
</li>
<li
id="p8"
data-extra-info="Super important conference! Fictional but
still!"
class="card"
>
<h2>Friday</h2>
</li>
</ul>
</section>
<section id="active-projects">
<header>
<h2>Active Projects</h2>
</header>
<ul id = 'active'>
<li
id="p1"
data-extra-info="Got lifetime access, but would be nice to
finish it soon!"
class="card"
>
<h2>Finish the Course</h2>
<p>Finish the course within the next two weeks.</p>
<button class="alt">More Info</button>
<button>Finish</button>
</li>
<li
id="p2"
data-extra-info="Not really a business topic but still
important."
class="card"
>
<h2>Buy Groceries</h2>
<p>Don't forget to pick up groceries today.</p>
<button class="alt">More Info</button>
<button>Finish</button>
</li>
</ul>
</section>
<section id="finished-projects">
<header>
<h2>Finished Projects</h2>
</header>
<ul>
<li
id="p3"
data-extra-info="Super important conference! Fictional but
still!"
class="card"
>
<h2>Book Hotel</h2>
<p>
Academind conference takes place in December, don't forget to
book a hotel.
</p>
<button class="alt">More Info</button>
<button>Activate</button>
</li>
</ul>
</section>
</div>
<button id = "addButton" class='add_Button'>ADD NEW</button>
< /body>
</html>
```css
* {
box-sizing: border-box;
}
html {
font-family: sans-serif;
}
body {
margin: 0;
}
#main-header {
width: 100%;
height: 6rem;
display: flex;
justify-content: center;
align-items: center;
background: #a3d2ca;
}
#main-header h1 {
color: white;
margin: 0;
}
footer {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
text-align: center;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
margin: 1rem 0;
}
section {
margin: 1rem auto;
width: 40rem;
max-width: 90%;
height: 100%;
border-radius: 10px;
}
section ul {
padding: 1rem;
max-height: 30rem;
overflow: scroll;
}
.Days {
padding: 1rem;
max-height: 20rem;
background: #d49a89;
padding: 1rem;
display: flex;
justify-content: space-between;
align-items: center;
/*border: 1px solid #ff0062;*/
margin: 0;
}
section > h2 {
color: white;
margin: 0;
border-radius: 10px;
}
button {
font: inherit;
background: #f7d1ba;
color: white;
border: 1px solid #f7d1ba;
padding: 0.5rem 1.5rem;
cursor: pointer;
}
button.alt {
background: white;
color: #ff0062;
}
button:focus {
outline: none;
}
button:hover,
button:active {
background: #f7d1ba;
border-color: #5eaaa8;
color: white;
}
.card {
border-radius: 10px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
padding: 1rem;
background: white;
}
#active-projects {
border: 2px solid #d49a89;
margin: 10px;
width: 30%;
border-radius: 10px;
}
#active-projects > header {
background: #d49a89;
padding: 1rem;
display: flex;
justify-content: space-between;
align-items: center;
}
#active-projects header h2 {
color: white;
margin: 0;
}
#finished-projects {
border: 2px solid #d49a89;
margin: 10px;
width: 30%;
border-radius: 10px;
}
#finished-projects > header {
background: #d49a89;
padding: 1rem;
display: flex;
justify-content: space-between;
align-items: center;
}
#finished-projects header h2 {
color: white;
margin: 0;
border-radius: 10px;
}
div {
display: flex;
flex-direction: row;
align-items: stretch;
justify-content: center;
height: 35rem;
}
#days-projects {
border: 2px solid #d49a89;
margin: 10px;
width: 30%;
border-radius: 10px;
}
#days-projects > header {
background: #d49a89;
padding: 1rem;
display: flex;
justify-content: space-between;
align-items: center;
}
#days-projects header h2 {
color: white;
margin: 0;
}
#days-projects li:hover {
background: #5eaaa8;
}
.add_Button {
align-items: center;
border: solid red;
}
```
It seems like there may be multiple problems (as #CodeCreate mentions, you are adding an li inside an li, and I'm not sure why you would call createNewButton twice), but I suspect the main issue you're asking about is with your addEventListener call.
You need to pass addEventListener a function to run when the event fires.
You're trying to pass this.addNewListItemHandler, but because you have added parentheses at its end, you are invoking the function immediately, rather than attaching it to run when the button is clicked.
Try rewriting your createNewButton method as:
newButton.addEventListener(
'click',
this.addNewListItemHandler
);
Try instantiating the class after it's defined:
let daysOfWeek = new DaysOfWeek
It's probable that this doesn't need to be a class to begin with, but since that's more a design decision, I'll leave that for you to research and decide.

Vue.js custom select component with v-model

I want to create a custom select component in Vue.js. Since I need specific options styling, I need to create 'select' made of div's etc that looks and acts like a real html select.
Currently I have something like this:
Vue.component('child', {
template: `<div class="component-container" #click="showOptions = !showOptions">
<div class="component__select">
<span class="component__select--name">Select Fruit</span>
<span class="c-arrow-down" v-if="!showOptions"></span>
<span class="c-arrow-up" v-if="showOptions"></span>
</div>
<ul class="component__select-options" v-if="showOptions" >
<li class="select--option" v-for="option in options">
<label> <input type="checkbox" :value="option"/> {{option.name}}</label>
</li>
</ul>
</div>`,
methods: {
selectOption(option) {
this.$emit('option', option)
}
},
data: () => ({
showOptions: false,
}),
props: ['options']
});
var vm = new Vue({
el: '#app',
data: () => ({
options: [
{id: 0, name: 'Apple'},
{id: 1, name: 'Banana'},
{id: 2, name: 'Orange'},
{id: 2, name: 'Strawberry'},
],
selectedFruit: ''
}),
})
.component__select {
height: 38px;
background-color: #F5F7FA;
border: 1px solid #dddddd;
line-height: 38px;
display: grid;
max-width: 500px;
grid-template-columns: 10fr 1fr;
}
.component__select--name {
font-size: 0.8rem;
padding: 0 0 0 25px;
cursor: pointer;
}
.c-arrow-down {
justify-self: end;
}
.component__select-options {
max-height: 180px;
border: 1px solid #dddddd;
border-top: none;
overflow: auto;
position: absolute;
z-index: 1500;
max-width: 500px;
width: 500px;
margin: 0;
padding: 0;
}
.select--option {
height: 35px;
display: grid;
align-content: center;
padding: 0 0 0 25px;
background-color: #f5f5fa;
border-bottom: 1px solid #dddddd;
}
.select--option:last-child {
border-bottom: none;
}
.select--option:nth-child(2n) {
background-color: #ffffff;
}
.select--option input{
display: none;
}
.single-option {
height: 55px;
background-color: #2595ec;
font-size: 0.8rem;
border: 1px solid red;
}
.cust-sel {
width: 200px;
height: 38px;
background-color: #f5f5fa;
border: 1px solid #dddddd;
}
.cust-sel:focus {
outline-width: 0;
}
<html>
<head>
<title>An example</title>
</head>
<body>
<div id="app">
<span> This is parent component</span>
<p>I want to have data from select here: "{{selectedFruit}}"</p>
<child :options="options" v-model="selectedFruit"></child>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</body>
</html>
But my problem is now how to return data from child to parent component using v-model on child component.
(I know I could emit data from child component and do:
<custom-select :options="someOptions" #selected="setSelectedOption"/>
but I need it to be reusable and writing more and more methods to retrieve data from every select in parent component is not exactly how it should work I think.)
Also I need to have an entire object returned, not only ID. (that's why i've got :value="option")
Any ideas?
As Vue Guide said:
v-model is essentially syntax sugar for updating data on user input
events, plus special care for some edge cases.
The syntax sugar will be like:
the directive=v-model will bind value, then listen input event to make change like v-bind:value="val" v-on:input="val = $event.target.value"
So for your use case, you need to create one prop=value, then emit the selected option with event=input.
Like below demo (bind/emit the whole option object):
Vue.config.productionTip = false
Vue.component('child', {
template: `<div class="component-container" #click="showOptions = !showOptions">
<div class="component__select">
<span class="component__select--name">{{value ? value.name : 'Select Fruit'}}</span>
<span class="c-arrow-down" v-if="!showOptions"></span>
<span class="c-arrow-up" v-if="showOptions"></span>
</div>
<ul class="component__select-options" v-if="showOptions" >
<li class="select--option" v-for="option in options" #click="selectOption(option)">
<label> <input type="checkbox" :value="option"/> {{option.name}}</label>
</li>
</ul>
</div>`,
methods: {
selectOption(option) {
this.$emit('input', option)
}
},
data: () => ({
showOptions: false
}),
props: ['options', 'value']
});
var vm = new Vue({
el: '#app',
data: () => ({
options: [
{id: 0, name: 'Apple'},
{id: 1, name: 'Banana'},
{id: 2, name: 'Orange'},
{id: 2, name: 'Strawberry'},
],
selectedFruit: ''
}),
})
.component__select {
height: 38px;
background-color: #F5F7FA;
border: 1px solid #dddddd;
line-height: 38px;
display: grid;
max-width: 500px;
grid-template-columns: 10fr 1fr;
}
.component__select--name {
font-size: 0.8rem;
padding: 0 0 0 25px;
cursor: pointer;
}
.c-arrow-down {
justify-self: end;
}
.component__select-options {
max-height: 180px;
border: 1px solid #dddddd;
border-top: none;
overflow: auto;
position: absolute;
z-index: 1500;
max-width: 500px;
width: 500px;
margin: 0;
padding: 0;
}
.select--option {
height: 35px;
display: grid;
align-content: center;
padding: 0 0 0 25px;
background-color: #f5f5fa;
border-bottom: 1px solid #dddddd;
}
.select--option:last-child {
border-bottom: none;
}
.select--option:nth-child(2n) {
background-color: #ffffff;
}
.select--option input{
display: none;
}
.single-option {
height: 55px;
background-color: #2595ec;
font-size: 0.8rem;
border: 1px solid red;
}
.cust-sel {
width: 200px;
height: 38px;
background-color: #f5f5fa;
border: 1px solid #dddddd;
}
.cust-sel:focus {
outline-width: 0;
}
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<span> This is parent component</span>
<p>I want to have data from select here: "{{selectedFruit}}"</p>
<child :options="options" v-model="selectedFruit"></child>
</div>
When using v-model on custom component all you need is to declare a prop named 'value' and when you need the component to chance it emit an 'input' event.
Something like this:
<template>
<form #submit.prevent="$emit('onSearch',val)" class="form-perfil">
<div class="form-group col-md-12">
<input v-model="val" #input="$emit('input',val)"
placeholder="filtrar resultados" class="form-control">
</div>
</form>
</template>
<script>
module.exports = {
name: "CaixaFiltro",
props: ["value"],
data: _ => ({ val: "" }),
created() {
this.val = this.value
}
}
</script>
Then you can use (after register the component) it like this:
<caixa-filtro v-model="textoBusca" #onSearch="listar"></caixa-filtro>
You can find more detailed info there:

Search bar in React TS not working as expected

I used this example snippet written in ReactJS to try and create a search box in my website, which is written in React TS
https://codemyui.com/input-highlight-seen-tripadvisor/
However when I have tried to convert it, I get the following issues
1) Input is read only, ie I cannot type into it
2) I am not sure what to do with this bit of the style in the original CSS, as it does not compile when I paste it into my CSS
&:focus {
+ .input-highlight {
border-top: 3px solid #fbc91b;
}
}
Can someone point out what I have done wrong in the conversion to TS?
My React control
import * as React from 'react';
import './App.css';
interface ISearchBarState {
inputValue : string
}
class SearchBar extends React.Component<{}, ISearchBarState> {
constructor(props: any) {
super(props);
this.state = {
inputValue: ''
};
this.onInputChange = this.onInputChange.bind(this);
}
public render() {
const { inputValue } = this.state;
return (<div className='input-wrapper'>
<input
placeholder='Search...'
value={inputValue}
spellCheck={false}
/>
<span className='input-highlight'>
{ inputValue.replace(/ /g, "\u00a0") }
</span>
</div>);
}
private onInputChange(e: any) {
const { value } = e.target;
this.setState({
inputValue: value
});
}
}
export default SearchBar;
and my CSS
.input-wrapper {
position: relative;
width: 350px;
margin-left: 5px;
}
.input-highlight {
font-size: 16;
user-select: none;
line-height: 20;
border-top: 1px solid white;
position: absolute;
left: 0;
bottom: 0;
color: #999999;
max-width: 100%;
height: 0;
color: transparent;
font-family: Roboto Slab, sans-serif;
overflow: hidden;
border-top: 3px solid #fbc91b;
}
input {
height: 30px;
width: 100%;
min-width: 100%;
padding: 0;
border-radius: 0;
line-height: 2;
background-color: transparent;
color: #999999;
font-size: 16;
border: none;
outline: none;
border-bottom: 1px solid #666666;
font-family: Roboto Slab, sans-serif;
}
It looks like the bit of css in question
&:focus {
+ .input-highlight {
border-top: 3px solid #fbc91b;
}
}
is actually scss, you'd need to compile that bit to css first or manually compile it to css. Here, below I help to manually change it to css for you
input:focus .input-highlight{
border-top: 3px solid #fbc91b;
}
you can add this css snippet to your css file, put it below the input css block.

How to change an element’s CSS class and remove all other classes on click

How do I handle a case in AngularJS 2 where on click of an element it needs to change its own style, and if other elements have that style they need to have it removed — preferably in one function.
Similar to Angular.js How to change an elements css class on click and to remove all others, only in AngularJS 2, using TypeScript.
Component
https://plnkr.co/edit/Q2BoU4sNnXdaJB5vrZ8h?p=preview
//our root app component
import { NgModule} from '#angular/core'
import {BrowserModule} from '#angular/platform-browser'
import {Component} from '#angular/core';
#Component({
selector: 'my-app',
providers: [],
template: `
<div>
<div (click)="isClassVisible = !isClassVisible;" [ngClass]="{'my-class': isClassVisible }">
> I'm a div that gets styled on click
</div>
<div (click)="isClassVisible = !isClassVisible;" [ngClass]="{'my-class': isClassVisible }">
> I also want to be styled but only when Im clicked
</div>
<div (click)="isClassVisible = !isClassVisible;" [ngClass]="{'my-class': isClassVisible }">
> When one of us gets clicked the we want to be the only one with the style all others go back to normal
</div>
<div (click)="isClassVisible = !isClassVisible;" [ngClass]="{'my-class': isClassVisible }">
> I'm just here cause my creator likes even numbers
</div>
</div>
`,
styles: [
`
.my-class {
background-color: yellow;
}
`
]
})
class App {
isClassVisible: false;
constructor() {
}
}
#NgModule({
imports: [ BrowserModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
The easiest fix to your problem is to assign a unique ID to each included element together with employing another variable to hold selected ID. The logic to turn on my-class CSS class will now be based on the selected ID.
Your new HTML template:
<div (click)="toggleHighlight(1);" [ngClass]="{'my-class': highlightedDiv === 1}">
> I'm a div that gets styled on click
</div>
Your toggleHighlight function:
highlightedDiv: number;
toggleHighlight(newValue: number) {
if (this.highlightedDiv === newValue) {
this.highlightedDiv = 0;
}
else {
this.highlightedDiv = newValue;
}
}
Working Plnk: https://plnkr.co/edit/fNoXWhUhMaUoeMihbGYd?p=preview
One solution which worked for me in showing the active menu is using typescript variable name in class as in
class="{{ text1Class }}"
and assign the class name in typescript.
this.text1Class = "active";
or
this.text1Class = "inactive";
You need to have different style class like this
.inactive {
background-color : gray;
padding : 10px;
}
.active {
background-color : green;
padding : 10px;
}
Assign the class name inside the function
textOneClicked() : void {
this.text1Class = "active"; // set the active class
this.text2Class = this.text3Class = this.text4Class = "inactive"; // reset other classes
}
A working Plunker here
I have one hard solution to this problem:
<div (click)="onclick($event);" >
> I'm a div that gets styled on click
</div>
app:
class App {
constructor() {
}
onclick(event){
var l = event.target.parentElement.getElementsByClassName("my-class");
var count = l.length;
for(var i=0;i<count;i++){
l[i].className = "";
}
event.target.className = "my-class";
}
}
Plink: https://plnkr.co/edit/RHqL56GrTiV9olYE1Ars?p=preview
Html code
<div [ngClass]="'first-div'">
<h2 [ngClass]="'heading'">Log In</h2>
<div [ngClass]="content">
<input type="text" placeholder="Enter User Name" name="username" id="username"#username class="in-cl">
<i class="fa fa-user fa-edited" aria-hidden="true"></i>
<input type="{{isPassword ? 'password':'text'}}" placeholder="Password" name="password" id="mypassword" #password class="in-cl">
<i class="fa fa-lock fa-lock-edited" aria-hidden="true" id="lock-id" (click)="onclick()"></i>
<button type="button" class="in-cl" (click)="credential(username.value,password.value)" >SIGN IN</button>
</div>
<div class="forgot">
Forgot Password?
</div>
</div>
css code
.first-div{
width: 350px;
border: 2px solid black;
margin-left: auto;
margin-right: auto;
margin-top: 130px;
border-radius: 5px;
height: 400px;
background-color: black;
color: white;
}
.heading{
color: white;
text-align: center;
font-weight: 500;
/* background-color: white; */
}
.in-cl{
margin: 20px 20px 0px 20px;
border: 2px solid white;
border-radius: 15px;
height: 40px;
padding: 5px;
width: 300px;
outline: none;
color: black;
/* padding-right: 60px; */
}
::placeholder{
color: black;
}
div button{
background-color: #3aafa9;
color:black;
text-align: center;
border: none;
}
.forgot{
margin: 15px;
text-align: center;
font-weight: 550;
color: white;
}
/* .image{
position: absolute;
left: 825px;
top: 222px;
}
.lock-image{
position: absolute;
left: 825px;
top: 282px;
} */
/* edited */
.fa-user:before{
color: black;
}
.fa-lock:before{
color: black;
}
.fa-unlock:before{
color: black;
}
.fa-edited{
top: 228px;
left: 770px;
position: absolute;
width: 28px;
}
.fa-lock-edited{
top: 287px;
left: 772px;
position: absolute;
}
a{
color: white;
}
ts code
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import swal from 'sweetalert2';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent{
username:string="pavithra";
password:string="8792415337abcd";
p = document.getElementById('mypassword');
constructor(private router:Router) {}
credential(username:string,password:string){
if(this.username==username && this.password==password ){
this.router.navigate(['/home'])
swal.fire({title:'Signed in successfully', confirmButtonColor:'#3aafa9', type:'success'})
}
else{
this.router.navigate(['/login'])
swal.fire({title:'Invalid Username or Password',type:'warning',position:'top-end'})
}
}
isPassword = true;
onclick(){
let body = document.getElementById('lock-id')
if (body.classList) {
body.classList.toggle("fa-unlock");
this.isPassword = !(this.isPassword);
} else {
var classes = body.className.split(" ");
console.log(classes)
var i = classes.indexOf("fa-lock");
if (i >= 0)
classes.splice(i, 1);
else
classes.push("fa-unlock");
body.className = classes.join(" ");
}
}
}

Categories

Resources