What made you build this?
One of the most difficult coding tasks I had at UPS was to create a colorpicker from scratch. I had gotten used to coding tables, forms, content, etc. A colorpicker? WHEW!
It challenged my understanding of Angular, accessibility, and my overall confidence in myself. Here is a mini version of what I did:
01
We are ultimately going to make a grid (hence the nested *ngFor*
), but lets keep it simple for now. In each square, there will be a radio button and an assigned color hex value
<!--Columns of Colors; There will be nine of these--> <div *ngFor="let group of colorGroup" class="color-column"> <!--Wrapper for an individual color square --> <div *ngFor="let colorGroup of group.colorGroup;let i = index" class="color-radio-wrapper"> <label [ngStyle]="{'background-color': '#' + colorGroup.colorHexValue}" for="{{group.colorGroupName}}{{i}}"> <input type="radio" id="{{group.colorGroupName}}{{i}}" name="colorpickerGroup" value="{{colorGroup.colorHexValue}}" [(ngModel)]="colorHexValue"> {{colorGroup.colorHexValue}} </label> </div> </div> <!--Where the Selected Color Will Appear--> <div [ngStyle]="{'background-color': '#' + colorHexValue}" class="color-block"></div>
/*Selected Color Box */ .color-block { width: 500px; height: 500px; }
import { Component, OnInit } from '@angular/core'; import * as data from './colors.json'; //Imports JSON file where color hex values are located @Component({ selector: 'app-colorpicker', templateUrl: './colorpicker.component.html', styleUrls: ['./colorpicker.component.css'] }) export class ColorpickerComponent implements OnInit { colorGroup: any = (data as any).default; colorHexValue!: string; constructor() { } ngOnInit() { console.log(data); } }
[ {
"colorGroupName": "pomegranate", "colorGroup" : [ { "id": 1, "colorHexValue":"F9EBEA" }, { "id": 2, "colorHexValue":"F2D7D5" }, { "id": 3, "colorHexValue":"E6B0AA" }, { "id": 4, "colorHexValue":"D98880" }, { "id": 5, "colorHexValue":"CD6155" }, { "id": 6, "colorHexValue":"C0392B" }, { "id": 7, "colorHexValue":"A93226" }, { "id": 8, "colorHexValue":"922B21" }, { "id": 9, "colorHexValue":"7B241C" }, { "id": 10, "colorHexValue":"641E16" } ] } ]

So Why Not Use <input type="color"/>
?
Oh, how I wish I could have! Unfortunately, this input type is only compatible in versions of IE 11 and later. My dev solution had to support at least IE 10.
02
Now that we have some basic functionality, lets expand our JSON to include all the colors we want and add more CSS to create and style that grid
<div id="outer"> <div id="container"> <div class="colorpicker-container"> <!--Columns of Colors; There will be nine of these--> <div *ngFor="let group of colorGroup" class="color-column"> <!--Wrapper for an individual color square --> <ng-container *ngFor="let colorGroup of group.colorGroup;let i = index"> <div class="color-radio-wrapper"> <label class="color-radio-label" [ngStyle]="{'background-color': '#' + colorGroup.colorHexValue}" for="{{group.colorGroupName}}{{i}}"> <input class="color-radio-input sr-only" type="radio" id="{{group.colorGroupName}}{{i}}" name="colorpickerGroup" value="{{colorGroup.colorHexValue}}" [(ngModel)]="colorSelected"> </label> </div> </ng-container> </div> </div> <!-- Where A Valid Color Will Appear --> <div class="color-block-wrapper"> <div [ngStyle]="{'background-color': '#' + colorSelected}" class="color-block"></div> </div> </div> </div>
/*optional*/ body { margin: 0px; background: #333; } /*BEGIN Centering Our Colorpicker */ #outer { position: relative; width: 100%; height: 100vh; } #outer #container { background-color: #f3f3f3; width: 100%; max-width: 672px; position: absolute; transform: translate(-50%, -50%); left: 50%; top: 50%; border-radius: 0.25em; } /*END Centering Our Colorpicker */ /*Color Column*/ .color-column { width: 40px; float: left; display: block; border: 1px solid #eaeaea; border-bottom: 0px; border-radius: 0.25em; } /*Color Radio*/ .color-radio-wrapper { height: 40px; } /*Color Label*/ .color-radio-label { width: 100%; font-size: 33px; /*This helps to control the height of each individual square */ } /*Color Input*/ .color-radio-input { width: 100%; cursor: pointer; margin: 0; } /* BEGIN: Selected Color Box */ .color-block-wrapper { display: flex; width: 100%; height: 150px; } .color-block { width: 100%; margin: 10px; border-radius: 0.25em; } /* END: Selected Color Box */
import { Component, OnInit } from '@angular/core'; import * as data from './colors.json'; //Imports JSON file where color hex values are located @Component({ selector: 'app-colorpicker', templateUrl: './colorpicker.component.html', styleUrls: ['./colorpicker.component.css'] }) export class ColorpickerComponent implements OnInit { colorGroup: any = (data as any).default; colorHexValue!: string; constructor() { } ngOnInit() { console.log(data); } }
[ { "colorGroupName" : "pomegranate", "colorGroup" : [ { "id": 1, "colorHexValue":"F9EBEA" }, { "id": 2, "colorHexValue":"F2D7D5" }, { "id": 3, "colorHexValue":"E6B0AA" }, { "id": 4, "colorHexValue":"D98880" }, { "id": 5, "colorHexValue":"CD6155" }, { "id": 6, "colorHexValue":"C0392B" }, { "id": 7, "colorHexValue":"A93226" }, { "id": 8, "colorHexValue":"922B21" }, { "id": 9, "colorHexValue":"7B241C" }, { "id": 10, "colorHexValue":"641E16" } ] }, { "colorGroupName" : "alizarin", "colorGroup" : [ { "id": 1, "colorHexValue":"FDEDEC" }, { "id": 2, "colorHexValue":"FADBD8" }, { "id": 3, "colorHexValue":"F5B7B1" }, { "id": 4, "colorHexValue":"F1948A" }, { "id": 5, "colorHexValue":"EC7063" }, { "id": 6, "colorHexValue":"E74C3C" }, { "id": 7, "colorHexValue":"CB4335" }, { "id": 8, "colorHexValue":"B03A2E" }, { "id": 9, "colorHexValue":"943126" }, { "id": 10, "colorHexValue":"78281F" } ] }, { "colorGroupName" : "amethyst", "colorGroup" : [ { "id": 1, "colorHexValue":"F5EEF8" }, { "id": 2, "colorHexValue":"EBDEF0" }, { "id": 3, "colorHexValue":"D7BDE2" }, { "id": 4, "colorHexValue":"C39BD3" }, { "id": 5, "colorHexValue":"AF7AC5" }, { "id": 6, "colorHexValue":"9B59B6" }, { "id": 7, "colorHexValue":"884EA0" }, { "id": 8, "colorHexValue":"76448A" }, { "id": 9, "colorHexValue":"633974" }, { "id": 10, "colorHexValue":"512E5F" } ] }, { "colorGroupName" : "wisteria", "colorGroup" : [ { "id": 1, "colorHexValue":"F4ECF7" }, { "id": 2, "colorHexValue":"E8DAEF" }, { "id": 3, "colorHexValue":"D2B4DE" }, { "id": 4, "colorHexValue":"BB8FCE" }, { "id": 5, "colorHexValue":"A569BD" }, { "id": 6, "colorHexValue":"8E44AD" }, { "id": 7, "colorHexValue":"7D3C98" }, { "id": 8, "colorHexValue":"6C3483" }, { "id": 9, "colorHexValue":"5B2C6F" }, { "id": 10, "colorHexValue":"4A235A" } ] }, { "colorGroupName" : "belize", "colorGroup" : [ { "id": 1, "colorHexValue":"EAF2F8" }, { "id": 2, "colorHexValue":"D4E6F1" }, { "id": 3, "colorHexValue":"A9CCE3" }, { "id": 4, "colorHexValue":"7FB3D5" }, { "id": 5, "colorHexValue":"5499C7" }, { "id": 6, "colorHexValue":"2980B9" }, { "id": 7, "colorHexValue":"2471A3" }, { "id": 8, "colorHexValue":"1F618D" }, { "id": 9, "colorHexValue":"1A5276" }, { "id": 10, "colorHexValue":"154360" } ] }, { "colorGroupName" : "river", "colorGroup" : [ { "id": 1, "colorHexValue":"EBF5FB" }, { "id": 2, "colorHexValue":"D6EAF8" }, { "id": 3, "colorHexValue":"AED6F1" }, { "id": 4, "colorHexValue":"85C1E9" }, { "id": 5, "colorHexValue":"5DADE2" }, { "id": 6, "colorHexValue":"3498DB" }, { "id": 7, "colorHexValue":"2E86C1" }, { "id": 8, "colorHexValue":"21618C" }, { "id": 9, "colorHexValue":"1A5276" }, { "id": 10, "colorHexValue":"1B4F72" } ] }, { "colorGroupName" : "ocean", "colorGroup" : [ { "id": 1, "colorHexValue":"E8F8F5" }, { "id": 2, "colorHexValue":"D1F2EB" }, { "id": 3, "colorHexValue":"A3E4D7" }, { "id": 4, "colorHexValue":"76D7C4" }, { "id": 5, "colorHexValue":"48C9B0" }, { "id": 6, "colorHexValue":"1ABC9C" }, { "id": 7, "colorHexValue":"17A589" }, { "id": 8, "colorHexValue":"148F77" }, { "id": 9, "colorHexValue":"117864" }, { "id": 10, "colorHexValue":"0E6251" } ] }, { "colorGroupName": "nephritis", "colorGroup" : [ { "id": 1, "colorHexValue":"E8F6F3" }, { "id": 2, "colorHexValue":"D0ECE7" }, { "id": 3, "colorHexValue":"A2D9CE" }, { "id": 4, "colorHexValue":"73C6B6" }, { "id": 5, "colorHexValue":"45B39D" }, { "id": 6, "colorHexValue":"16A085" }, { "id": 7, "colorHexValue":"138D75" }, { "id": 8, "colorHexValue":"117A65" }, { "id": 9, "colorHexValue":"0E6655" }, { "id": 10, "colorHexValue":"0B5345" } ] }, { "colorGroupName": "emerald", "colorGroup" : [ { "id": 1, "colorHexValue":"E9F7EF" }, { "id": 2, "colorHexValue":"D4EFDF" }, { "id": 3, "colorHexValue":"A9DFBF" }, { "id": 4, "colorHexValue":"7DCEA0" }, { "id": 5, "colorHexValue":"52BE80" }, { "id": 6, "colorHexValue":"27AE60" }, { "id": 7, "colorHexValue":"229954" }, { "id": 8, "colorHexValue":"1E8449" }, { "id": 9, "colorHexValue":"196F3D" }, { "id": 10, "colorHexValue":"145A32" } ] }, { "colorGroupName": "sunflower", "colorGroup" : [ { "id": 1, "colorHexValue":"EAFAF1" }, { "id": 2, "colorHexValue":"D5F5E3" }, { "id": 3, "colorHexValue":"ABEBC6" }, { "id": 4, "colorHexValue":"82E0AA" }, { "id": 5, "colorHexValue":"58D68D" }, { "id": 6, "colorHexValue":"2ECC71" }, { "id": 7, "colorHexValue":"28B463" }, { "id": 8, "colorHexValue":"239B56" }, { "id": 9, "colorHexValue":"1D8348" }, { "id": 10, "colorHexValue":"186A3B" } ] }, { "colorGroupName": "orange", "colorGroup" : [ { "id": 1, "colorHexValue":"FEF9E7" }, { "id": 2, "colorHexValue":"FCF3CF" }, { "id": 3, "colorHexValue":"F9E79F" }, { "id": 4, "colorHexValue":"F7DC6F" }, { "id": 5, "colorHexValue":"F4D03F" }, { "id": 6, "colorHexValue":"F1C40F" }, { "id": 7, "colorHexValue":"D4AC0D" }, { "id": 8, "colorHexValue":"B7950B" }, { "id": 9, "colorHexValue":"9A7D0A" }, { "id": 10, "colorHexValue":"7D6608" } ] }, { "colorGroupName":"carrot", "colorGroup" : [ { "id": 1, "colorHexValue":"FEF9E7" }, { "id": 2, "colorHexValue":"FDEBD0" }, { "id": 3, "colorHexValue":"FAD7A0" }, { "id": 4, "colorHexValue":"F8C471" }, { "id": 5, "colorHexValue":"F5B041" }, { "id": 6, "colorHexValue":"F39C12" }, { "id": 7, "colorHexValue":"D68910" }, { "id": 8, "colorHexValue":"B9770E" }, { "id": 9, "colorHexValue":"9C640C" }, { "id": 10, "colorHexValue":"7E5109" } ] }, { "colorGroupName": "pumpkin", "colorGroup" : [ { "id": 1, "colorHexValue":"FDF2E9" }, { "id": 2, "colorHexValue":"FAE5D3" }, { "id": 3, "colorHexValue":"F5CBA7" }, { "id": 4, "colorHexValue":"F0B27A" }, { "id": 5, "colorHexValue":"EB984E" }, { "id": 6, "colorHexValue":"E67E22" }, { "id": 7, "colorHexValue":"CA6F1E" }, { "id": 8, "colorHexValue":"AF601A" }, { "id": 9, "colorHexValue":"935116" }, { "id": 10, "colorHexValue":"784212" } ] }, { "colorGroupName": "concrete", "colorGroup" : [ { "id": 1, "colorHexValue":"F4F6F6" }, { "id": 2, "colorHexValue":"EAEDED" }, { "id": 3, "colorHexValue":"D5DBDB" }, { "id": 4, "colorHexValue":"BFC9CA" }, { "id": 5, "colorHexValue":"AAB7B8" }, { "id": 6, "colorHexValue":"95A5A6" }, { "id": 7, "colorHexValue":"839192" }, { "id": 8, "colorHexValue":"717D7E" }, { "id": 9, "colorHexValue":"5F6A6A" }, { "id": 10, "colorHexValue":"4D5656" } ] }, { "colorGroupName": "asbestos", "colorGroup" : [ { "id": 1, "colorHexValue":"F2F4F4" }, { "id": 2, "colorHexValue":"E5E8E8" }, { "id": 3, "colorHexValue":"CCD1D1" }, { "id": 4, "colorHexValue":"B2BABB" }, { "id": 5, "colorHexValue":"99A3A4" }, { "id": 6, "colorHexValue":"7F8C8D" }, { "id": 7, "colorHexValue":"707B7C" }, { "id": 8, "colorHexValue":"616A6B" }, { "id": 9, "colorHexValue":"515A5A" }, { "id": 10, "colorHexValue":"424949" } ] }, { "colorGroupName": "asphalt", "colorGroup" : [ { "id": 1, "colorHexValue":"EBEDEF" }, { "id": 2, "colorHexValue":"D6DBDF" }, { "id": 3, "colorHexValue":"AEB6BF" }, { "id": 4, "colorHexValue":"85929E" }, { "id": 5, "colorHexValue":"5D6D7E" }, { "id": 6, "colorHexValue":"34495E" }, { "id": 7, "colorHexValue":"2E4053" }, { "id": 8, "colorHexValue":"283747" }, { "id": 9, "colorHexValue":"212F3C" }, { "id": 10, "colorHexValue":"1B2631" } ] } ]

03
Now, let’s “remove” those radio buttons by decreasing the opacity and create a focused state so our users have a visual cue on which square has been selected.
<div id="outer"> <div id="container"> <div class="colorpicker-container"> <!--Columns of Colors; There will be nine of these--> <div *ngFor="let group of colorGroup" class="color-column"> <!--Wrapper for an individual color square --> <ng-container *ngFor="let colorGroup of group.colorGroup;let i = index"> <div class="color-radio-wrapper" [ngClass]="{'color-is-selected': colorGroup.colorHexValue == colorSelected}"> <label class="color-radio-label" [ngStyle]="{'background-color': '#' + colorGroup.colorHexValue}" for="{{group.colorGroupName}}{{i}}"> <input class="color-radio-input sr-only" type="radio" id="{{group.colorGroupName}}{{i}}" name="colorpickerGroup" value="{{colorGroup.colorHexValue}}" [(ngModel)]="colorSelected"> </label> </div> </ng-container> </div> </div> <!-- Where A Valid Color Will Appear --> <div class="color-block-wrapper"> <div [ngStyle]="{'background-color': '#' + colorSelected}" class="color-block"></div> </div> </div> </div>
/*optional*/ body { margin: 0px; background: #333; } /*BEGIN Centering Our Colorpicker */ #outer { position: relative; width: 100%; height: 100vh; } #outer #container { background-color: #f3f3f3; width: 100%; max-width: 672px; position: absolute; transform: translate(-50%, -50%); left: 50%; top: 50%; border-radius: 0.25em; } /*END Centering Our Colorpicker */ /*Color Column*/ .color-column { width: 40px; float: left; display: block; border: 1px solid #eaeaea; border-bottom: 0px; border-radius: 0.25em; } /*Color Radio*/ .color-radio-wrapper { height: 40px; } /*Color Label*/ .color-radio-label { width: 100%; font-size: 33px; /*This helps to control the height of each individual square */ } /*Color Input*/ .color-radio-input { width: 100%; cursor: pointer; margin: 0;
opacity: 0;/*Makes the circled radio button "disappear"*/ }
/*Focused Input*/ .color-radio-wrapper.color-is-selected {
outline: 1px solid blue;
} /* BEGIN: Selected Color Box */ .color-block-wrapper { display: flex; width: 100%; height: 150px; } .color-block { width: 100%; margin: 10px; border-radius: 0.25em; } /* END: Selected Color Box */
import { Component, OnInit } from '@angular/core'; import * as data from './colors.json'; //Imports JSON file where color hex values are located @Component({ selector: 'app-colorpicker', templateUrl: './colorpicker.component.html', styleUrls: ['./colorpicker.component.css'] }) export class ColorpickerComponent implements OnInit { colorGroup: any = (data as any).default; colorHexValue!: string; constructor() { } ngOnInit() { console.log(data); } }
[ { "colorGroupName" : "pomegranate", "colorGroup" : [ { "id": 1, "colorHexValue":"F9EBEA" }, { "id": 2, "colorHexValue":"F2D7D5" }, { "id": 3, "colorHexValue":"E6B0AA" }, { "id": 4, "colorHexValue":"D98880" }, { "id": 5, "colorHexValue":"CD6155" }, { "id": 6, "colorHexValue":"C0392B" }, { "id": 7, "colorHexValue":"A93226" }, { "id": 8, "colorHexValue":"922B21" }, { "id": 9, "colorHexValue":"7B241C" }, { "id": 10, "colorHexValue":"641E16" } ] }, { "colorGroupName" : "alizarin", "colorGroup" : [ { "id": 1, "colorHexValue":"FDEDEC" }, { "id": 2, "colorHexValue":"FADBD8" }, { "id": 3, "colorHexValue":"F5B7B1" }, { "id": 4, "colorHexValue":"F1948A" }, { "id": 5, "colorHexValue":"EC7063" }, { "id": 6, "colorHexValue":"E74C3C" }, { "id": 7, "colorHexValue":"CB4335" }, { "id": 8, "colorHexValue":"B03A2E" }, { "id": 9, "colorHexValue":"943126" }, { "id": 10, "colorHexValue":"78281F" } ] }, { "colorGroupName" : "amethyst", "colorGroup" : [ { "id": 1, "colorHexValue":"F5EEF8" }, { "id": 2, "colorHexValue":"EBDEF0" }, { "id": 3, "colorHexValue":"D7BDE2" }, { "id": 4, "colorHexValue":"C39BD3" }, { "id": 5, "colorHexValue":"AF7AC5" }, { "id": 6, "colorHexValue":"9B59B6" }, { "id": 7, "colorHexValue":"884EA0" }, { "id": 8, "colorHexValue":"76448A" }, { "id": 9, "colorHexValue":"633974" }, { "id": 10, "colorHexValue":"512E5F" } ] }, { "colorGroupName" : "wisteria", "colorGroup" : [ { "id": 1, "colorHexValue":"F4ECF7" }, { "id": 2, "colorHexValue":"E8DAEF" }, { "id": 3, "colorHexValue":"D2B4DE" }, { "id": 4, "colorHexValue":"BB8FCE" }, { "id": 5, "colorHexValue":"A569BD" }, { "id": 6, "colorHexValue":"8E44AD" }, { "id": 7, "colorHexValue":"7D3C98" }, { "id": 8, "colorHexValue":"6C3483" }, { "id": 9, "colorHexValue":"5B2C6F" }, { "id": 10, "colorHexValue":"4A235A" } ] }, { "colorGroupName" : "belize", "colorGroup" : [ { "id": 1, "colorHexValue":"EAF2F8" }, { "id": 2, "colorHexValue":"D4E6F1" }, { "id": 3, "colorHexValue":"A9CCE3" }, { "id": 4, "colorHexValue":"7FB3D5" }, { "id": 5, "colorHexValue":"5499C7" }, { "id": 6, "colorHexValue":"2980B9" }, { "id": 7, "colorHexValue":"2471A3" }, { "id": 8, "colorHexValue":"1F618D" }, { "id": 9, "colorHexValue":"1A5276" }, { "id": 10, "colorHexValue":"154360" } ] }, { "colorGroupName" : "river", "colorGroup" : [ { "id": 1, "colorHexValue":"EBF5FB" }, { "id": 2, "colorHexValue":"D6EAF8" }, { "id": 3, "colorHexValue":"AED6F1" }, { "id": 4, "colorHexValue":"85C1E9" }, { "id": 5, "colorHexValue":"5DADE2" }, { "id": 6, "colorHexValue":"3498DB" }, { "id": 7, "colorHexValue":"2E86C1" }, { "id": 8, "colorHexValue":"21618C" }, { "id": 9, "colorHexValue":"1A5276" }, { "id": 10, "colorHexValue":"1B4F72" } ] }, { "colorGroupName" : "ocean", "colorGroup" : [ { "id": 1, "colorHexValue":"E8F8F5" }, { "id": 2, "colorHexValue":"D1F2EB" }, { "id": 3, "colorHexValue":"A3E4D7" }, { "id": 4, "colorHexValue":"76D7C4" }, { "id": 5, "colorHexValue":"48C9B0" }, { "id": 6, "colorHexValue":"1ABC9C" }, { "id": 7, "colorHexValue":"17A589" }, { "id": 8, "colorHexValue":"148F77" }, { "id": 9, "colorHexValue":"117864" }, { "id": 10, "colorHexValue":"0E6251" } ] }, { "colorGroupName": "nephritis", "colorGroup" : [ { "id": 1, "colorHexValue":"E8F6F3" }, { "id": 2, "colorHexValue":"D0ECE7" }, { "id": 3, "colorHexValue":"A2D9CE" }, { "id": 4, "colorHexValue":"73C6B6" }, { "id": 5, "colorHexValue":"45B39D" }, { "id": 6, "colorHexValue":"16A085" }, { "id": 7, "colorHexValue":"138D75" }, { "id": 8, "colorHexValue":"117A65" }, { "id": 9, "colorHexValue":"0E6655" }, { "id": 10, "colorHexValue":"0B5345" } ] }, { "colorGroupName": "emerald", "colorGroup" : [ { "id": 1, "colorHexValue":"E9F7EF" }, { "id": 2, "colorHexValue":"D4EFDF" }, { "id": 3, "colorHexValue":"A9DFBF" }, { "id": 4, "colorHexValue":"7DCEA0" }, { "id": 5, "colorHexValue":"52BE80" }, { "id": 6, "colorHexValue":"27AE60" }, { "id": 7, "colorHexValue":"229954" }, { "id": 8, "colorHexValue":"1E8449" }, { "id": 9, "colorHexValue":"196F3D" }, { "id": 10, "colorHexValue":"145A32" } ] }, { "colorGroupName": "sunflower", "colorGroup" : [ { "id": 1, "colorHexValue":"EAFAF1" }, { "id": 2, "colorHexValue":"D5F5E3" }, { "id": 3, "colorHexValue":"ABEBC6" }, { "id": 4, "colorHexValue":"82E0AA" }, { "id": 5, "colorHexValue":"58D68D" }, { "id": 6, "colorHexValue":"2ECC71" }, { "id": 7, "colorHexValue":"28B463" }, { "id": 8, "colorHexValue":"239B56" }, { "id": 9, "colorHexValue":"1D8348" }, { "id": 10, "colorHexValue":"186A3B" } ] }, { "colorGroupName": "orange", "colorGroup" : [ { "id": 1, "colorHexValue":"FEF9E7" }, { "id": 2, "colorHexValue":"FCF3CF" }, { "id": 3, "colorHexValue":"F9E79F" }, { "id": 4, "colorHexValue":"F7DC6F" }, { "id": 5, "colorHexValue":"F4D03F" }, { "id": 6, "colorHexValue":"F1C40F" }, { "id": 7, "colorHexValue":"D4AC0D" }, { "id": 8, "colorHexValue":"B7950B" }, { "id": 9, "colorHexValue":"9A7D0A" }, { "id": 10, "colorHexValue":"7D6608" } ] }, { "colorGroupName":"carrot", "colorGroup" : [ { "id": 1, "colorHexValue":"FEF9E7" }, { "id": 2, "colorHexValue":"FDEBD0" }, { "id": 3, "colorHexValue":"FAD7A0" }, { "id": 4, "colorHexValue":"F8C471" }, { "id": 5, "colorHexValue":"F5B041" }, { "id": 6, "colorHexValue":"F39C12" }, { "id": 7, "colorHexValue":"D68910" }, { "id": 8, "colorHexValue":"B9770E" }, { "id": 9, "colorHexValue":"9C640C" }, { "id": 10, "colorHexValue":"7E5109" } ] }, { "colorGroupName": "pumpkin", "colorGroup" : [ { "id": 1, "colorHexValue":"FDF2E9" }, { "id": 2, "colorHexValue":"FAE5D3" }, { "id": 3, "colorHexValue":"F5CBA7" }, { "id": 4, "colorHexValue":"F0B27A" }, { "id": 5, "colorHexValue":"EB984E" }, { "id": 6, "colorHexValue":"E67E22" }, { "id": 7, "colorHexValue":"CA6F1E" }, { "id": 8, "colorHexValue":"AF601A" }, { "id": 9, "colorHexValue":"935116" }, { "id": 10, "colorHexValue":"784212" } ] }, { "colorGroupName": "concrete", "colorGroup" : [ { "id": 1, "colorHexValue":"F4F6F6" }, { "id": 2, "colorHexValue":"EAEDED" }, { "id": 3, "colorHexValue":"D5DBDB" }, { "id": 4, "colorHexValue":"BFC9CA" }, { "id": 5, "colorHexValue":"AAB7B8" }, { "id": 6, "colorHexValue":"95A5A6" }, { "id": 7, "colorHexValue":"839192" }, { "id": 8, "colorHexValue":"717D7E" }, { "id": 9, "colorHexValue":"5F6A6A" }, { "id": 10, "colorHexValue":"4D5656" } ] }, { "colorGroupName": "asbestos", "colorGroup" : [ { "id": 1, "colorHexValue":"F2F4F4" }, { "id": 2, "colorHexValue":"E5E8E8" }, { "id": 3, "colorHexValue":"CCD1D1" }, { "id": 4, "colorHexValue":"B2BABB" }, { "id": 5, "colorHexValue":"99A3A4" }, { "id": 6, "colorHexValue":"7F8C8D" }, { "id": 7, "colorHexValue":"707B7C" }, { "id": 8, "colorHexValue":"616A6B" }, { "id": 9, "colorHexValue":"515A5A" }, { "id": 10, "colorHexValue":"424949" } ] }, { "colorGroupName": "asphalt", "colorGroup" : [ { "id": 1, "colorHexValue":"EBEDEF" }, { "id": 2, "colorHexValue":"D6DBDF" }, { "id": 3, "colorHexValue":"AEB6BF" }, { "id": 4, "colorHexValue":"85929E" }, { "id": 5, "colorHexValue":"5D6D7E" }, { "id": 6, "colorHexValue":"34495E" }, { "id": 7, "colorHexValue":"2E4053" }, { "id": 8, "colorHexValue":"283747" }, { "id": 9, "colorHexValue":"212F3C" }, { "id": 10, "colorHexValue":"1B2631" } ] } ]

04
Lastly, lets add a text input with validation so our users can add custom hex values
<div id="outer"> <div id="container"> <div class="colorpicker-container"> <div *ngFor="let group of colorGroup" class="color-column"> <ng-container *ngFor="let colorGroup of group.colorGroup;let i = index"> <div class="color-radio-wrapper" [ngClass]="{'color-is-selected': colorGroup.colorHexValue == colorSelected}"> <label class="color-radio-label" [ngStyle]="{'background-color': '#' + colorGroup.colorHexValue}" for="{{group.colorGroupName}}{{i}}"> <input class="color-radio-input" type="radio" id="{{group.colorGroupName}}{{i}}" name="colorpickerGroup" value="{{colorGroup.colorHexValue}}" [(ngModel)]="colorSelected"> </label> </div> </ng-container> </div> </div> <!-- NEW: Where Users Can Input Custom Hex--> <form [formGroup]="angForm" novalidate class="hex-input-wrapper"> <label class="hex-label" for="hexInput">Hex Number </label> <div class="hex-input-group"> <span class="hex-input-group-text">#</span> <input formControlName="hexInput" class="hex-input" type="text" id="hexInput" name="hexInput" [(ngModel)]="colorSelected" maxlength="7" pattern="^([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$"> </div> <div class="hex-error-message" *ngIf="angForm.controls['hexInput'].invalid && (angForm.controls['hexInput'].dirty || angForm.controls['hexInput'].touched)"> <em>Format is (i.e.000 or 000000).</em> </div> </form> <div class="color-block-wrapper" > <div [ngStyle]="{'background-color': '#' + colorSelected}" class="color-block"></div> </div> </div> </div>
/*optional*/ body { margin: 0px; background: #333; } /*BEGIN Centering Our Colorpicker */ #outer { position: relative; width: 100%; height: 100vh; } #outer #container { background-color: #f3f3f3; width: 100%; max-width: 672px; position: absolute; transform: translate(-50%, -50%); left: 50%; top: 50%; border-radius: 0.25em; } /*END Centering Our Colorpicker */ /*Color Column*/ .color-column { width: 40px; float: left; display: block; border: 1px solid #eaeaea; border-bottom: 0px; border-radius: 0.25em; } /*Color Radio*/ .color-radio-wrapper { height: 40px; } /*Color Label*/ .color-radio-label { width: 100%; font-size: 33px; /*This helps to control the height of each individual square */ } /*Color Input*/ .color-radio-input { width: 100%; cursor: pointer; margin: 0; opacity: 0; } /* BEGIN: Selected Color Box */ .color-block-wrapper { display: flex; width: 100%; height: 150px; } .color-block { width: 100%; margin: 10px; border-radius: 0.25em; } /* END: Selected Color Box */ /*Selected/"Focused" State*/ .color-radio-wrapper.color-is-selected { outline: 1px solid blue; } /******* NEW CSS *************/ /*Hex Input Styles*/ .hex-input-wrapper { margin: 10px; display: inline-block; width: 50%; } /*Hex Label*/ .hex-label { display: inline-block; margin-bottom: .5rem; } /*Hex Input*/ .hex-input { display: block; height: 34px; font-size: 16px; position: relative; flex: 1 1 auto; width: 1%; min-width: 0; margin-left: -1px; border-top-left-radius: 0; border-bottom-left-radius: 0; border-style: solid; border-width: 1px; } .hex-input-group { position: relative; display: flex; flex-wrap: wrap; align-items: stretch; width: 100%; } .hex-input-group .hex-input-group-text { display: flex; align-items: center; padding: .375rem .75rem; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; text-align: center; white-space: nowrap; background-color: #e9ecef; border: 1px solid #ced4da; border-radius: .25rem; } /* Hex Input Error State */ .hex-input.ng-invalid:not(.ng-pristine) { border: 2px solid #D40000; } .hex-input.ng-invalid:not(.ng-pristine):focus { outline: 2px solid #D40000; } .hex-error-message { color: #D40000; padding-top: 10px; }
import { Component, OnInit } from '@angular/core'; import * as data from './colors.json'; //Imports JSON file where color hex values are located import { FormGroup, FormBuilder, Validators } from '@angular/forms'; //Needed for error handling @Component({ selector: 'app-colorpicker', templateUrl: './colorpicker.component.html', styleUrls: ['./colorpicker.component.css'] }) export class ColorpickerComponent implements OnInit { colorGroup: any = (data as any).default; colorSelected!: string; colorInput!: string; angForm!: FormGroup; //Initialize FormGroup Variable. constructor(private fb: FormBuilder) { this.createForm(); } //Generate Form Controls createForm() { this.angForm = this.fb.group({ hexInput: ['', Validators.required] }); } ngOnInit() { console.log(data); } }
[ { "colorGroupName" : "pomegranate", "colorGroup" : [ { "id": 1, "colorHexValue":"F9EBEA" }, { "id": 2, "colorHexValue":"F2D7D5" }, { "id": 3, "colorHexValue":"E6B0AA" }, { "id": 4, "colorHexValue":"D98880" }, { "id": 5, "colorHexValue":"CD6155" }, { "id": 6, "colorHexValue":"C0392B" }, { "id": 7, "colorHexValue":"A93226" }, { "id": 8, "colorHexValue":"922B21" }, { "id": 9, "colorHexValue":"7B241C" }, { "id": 10, "colorHexValue":"641E16" } ] }, { "colorGroupName" : "alizarin", "colorGroup" : [ { "id": 1, "colorHexValue":"FDEDEC" }, { "id": 2, "colorHexValue":"FADBD8" }, { "id": 3, "colorHexValue":"F5B7B1" }, { "id": 4, "colorHexValue":"F1948A" }, { "id": 5, "colorHexValue":"EC7063" }, { "id": 6, "colorHexValue":"E74C3C" }, { "id": 7, "colorHexValue":"CB4335" }, { "id": 8, "colorHexValue":"B03A2E" }, { "id": 9, "colorHexValue":"943126" }, { "id": 10, "colorHexValue":"78281F" } ] }, { "colorGroupName" : "amethyst", "colorGroup" : [ { "id": 1, "colorHexValue":"F5EEF8" }, { "id": 2, "colorHexValue":"EBDEF0" }, { "id": 3, "colorHexValue":"D7BDE2" }, { "id": 4, "colorHexValue":"C39BD3" }, { "id": 5, "colorHexValue":"AF7AC5" }, { "id": 6, "colorHexValue":"9B59B6" }, { "id": 7, "colorHexValue":"884EA0" }, { "id": 8, "colorHexValue":"76448A" }, { "id": 9, "colorHexValue":"633974" }, { "id": 10, "colorHexValue":"512E5F" } ] }, { "colorGroupName" : "wisteria", "colorGroup" : [ { "id": 1, "colorHexValue":"F4ECF7" }, { "id": 2, "colorHexValue":"E8DAEF" }, { "id": 3, "colorHexValue":"D2B4DE" }, { "id": 4, "colorHexValue":"BB8FCE" }, { "id": 5, "colorHexValue":"A569BD" }, { "id": 6, "colorHexValue":"8E44AD" }, { "id": 7, "colorHexValue":"7D3C98" }, { "id": 8, "colorHexValue":"6C3483" }, { "id": 9, "colorHexValue":"5B2C6F" }, { "id": 10, "colorHexValue":"4A235A" } ] }, { "colorGroupName" : "belize", "colorGroup" : [ { "id": 1, "colorHexValue":"EAF2F8" }, { "id": 2, "colorHexValue":"D4E6F1" }, { "id": 3, "colorHexValue":"A9CCE3" }, { "id": 4, "colorHexValue":"7FB3D5" }, { "id": 5, "colorHexValue":"5499C7" }, { "id": 6, "colorHexValue":"2980B9" }, { "id": 7, "colorHexValue":"2471A3" }, { "id": 8, "colorHexValue":"1F618D" }, { "id": 9, "colorHexValue":"1A5276" }, { "id": 10, "colorHexValue":"154360" } ] }, { "colorGroupName" : "river", "colorGroup" : [ { "id": 1, "colorHexValue":"EBF5FB" }, { "id": 2, "colorHexValue":"D6EAF8" }, { "id": 3, "colorHexValue":"AED6F1" }, { "id": 4, "colorHexValue":"85C1E9" }, { "id": 5, "colorHexValue":"5DADE2" }, { "id": 6, "colorHexValue":"3498DB" }, { "id": 7, "colorHexValue":"2E86C1" }, { "id": 8, "colorHexValue":"21618C" }, { "id": 9, "colorHexValue":"1A5276" }, { "id": 10, "colorHexValue":"1B4F72" } ] }, { "colorGroupName" : "ocean", "colorGroup" : [ { "id": 1, "colorHexValue":"E8F8F5" }, { "id": 2, "colorHexValue":"D1F2EB" }, { "id": 3, "colorHexValue":"A3E4D7" }, { "id": 4, "colorHexValue":"76D7C4" }, { "id": 5, "colorHexValue":"48C9B0" }, { "id": 6, "colorHexValue":"1ABC9C" }, { "id": 7, "colorHexValue":"17A589" }, { "id": 8, "colorHexValue":"148F77" }, { "id": 9, "colorHexValue":"117864" }, { "id": 10, "colorHexValue":"0E6251" } ] }, { "colorGroupName": "nephritis", "colorGroup" : [ { "id": 1, "colorHexValue":"E8F6F3" }, { "id": 2, "colorHexValue":"D0ECE7" }, { "id": 3, "colorHexValue":"A2D9CE" }, { "id": 4, "colorHexValue":"73C6B6" }, { "id": 5, "colorHexValue":"45B39D" }, { "id": 6, "colorHexValue":"16A085" }, { "id": 7, "colorHexValue":"138D75" }, { "id": 8, "colorHexValue":"117A65" }, { "id": 9, "colorHexValue":"0E6655" }, { "id": 10, "colorHexValue":"0B5345" } ] }, { "colorGroupName": "emerald", "colorGroup" : [ { "id": 1, "colorHexValue":"E9F7EF" }, { "id": 2, "colorHexValue":"D4EFDF" }, { "id": 3, "colorHexValue":"A9DFBF" }, { "id": 4, "colorHexValue":"7DCEA0" }, { "id": 5, "colorHexValue":"52BE80" }, { "id": 6, "colorHexValue":"27AE60" }, { "id": 7, "colorHexValue":"229954" }, { "id": 8, "colorHexValue":"1E8449" }, { "id": 9, "colorHexValue":"196F3D" }, { "id": 10, "colorHexValue":"145A32" } ] }, { "colorGroupName": "sunflower", "colorGroup" : [ { "id": 1, "colorHexValue":"EAFAF1" }, { "id": 2, "colorHexValue":"D5F5E3" }, { "id": 3, "colorHexValue":"ABEBC6" }, { "id": 4, "colorHexValue":"82E0AA" }, { "id": 5, "colorHexValue":"58D68D" }, { "id": 6, "colorHexValue":"2ECC71" }, { "id": 7, "colorHexValue":"28B463" }, { "id": 8, "colorHexValue":"239B56" }, { "id": 9, "colorHexValue":"1D8348" }, { "id": 10, "colorHexValue":"186A3B" } ] }, { "colorGroupName": "orange", "colorGroup" : [ { "id": 1, "colorHexValue":"FEF9E7" }, { "id": 2, "colorHexValue":"FCF3CF" }, { "id": 3, "colorHexValue":"F9E79F" }, { "id": 4, "colorHexValue":"F7DC6F" }, { "id": 5, "colorHexValue":"F4D03F" }, { "id": 6, "colorHexValue":"F1C40F" }, { "id": 7, "colorHexValue":"D4AC0D" }, { "id": 8, "colorHexValue":"B7950B" }, { "id": 9, "colorHexValue":"9A7D0A" }, { "id": 10, "colorHexValue":"7D6608" } ] }, { "colorGroupName":"carrot", "colorGroup" : [ { "id": 1, "colorHexValue":"FEF9E7" }, { "id": 2, "colorHexValue":"FDEBD0" }, { "id": 3, "colorHexValue":"FAD7A0" }, { "id": 4, "colorHexValue":"F8C471" }, { "id": 5, "colorHexValue":"F5B041" }, { "id": 6, "colorHexValue":"F39C12" }, { "id": 7, "colorHexValue":"D68910" }, { "id": 8, "colorHexValue":"B9770E" }, { "id": 9, "colorHexValue":"9C640C" }, { "id": 10, "colorHexValue":"7E5109" } ] }, { "colorGroupName": "pumpkin", "colorGroup" : [ { "id": 1, "colorHexValue":"FDF2E9" }, { "id": 2, "colorHexValue":"FAE5D3" }, { "id": 3, "colorHexValue":"F5CBA7" }, { "id": 4, "colorHexValue":"F0B27A" }, { "id": 5, "colorHexValue":"EB984E" }, { "id": 6, "colorHexValue":"E67E22" }, { "id": 7, "colorHexValue":"CA6F1E" }, { "id": 8, "colorHexValue":"AF601A" }, { "id": 9, "colorHexValue":"935116" }, { "id": 10, "colorHexValue":"784212" } ] }, { "colorGroupName": "concrete", "colorGroup" : [ { "id": 1, "colorHexValue":"F4F6F6" }, { "id": 2, "colorHexValue":"EAEDED" }, { "id": 3, "colorHexValue":"D5DBDB" }, { "id": 4, "colorHexValue":"BFC9CA" }, { "id": 5, "colorHexValue":"AAB7B8" }, { "id": 6, "colorHexValue":"95A5A6" }, { "id": 7, "colorHexValue":"839192" }, { "id": 8, "colorHexValue":"717D7E" }, { "id": 9, "colorHexValue":"5F6A6A" }, { "id": 10, "colorHexValue":"4D5656" } ] }, { "colorGroupName": "asbestos", "colorGroup" : [ { "id": 1, "colorHexValue":"F2F4F4" }, { "id": 2, "colorHexValue":"E5E8E8" }, { "id": 3, "colorHexValue":"CCD1D1" }, { "id": 4, "colorHexValue":"B2BABB" }, { "id": 5, "colorHexValue":"99A3A4" }, { "id": 6, "colorHexValue":"7F8C8D" }, { "id": 7, "colorHexValue":"707B7C" }, { "id": 8, "colorHexValue":"616A6B" }, { "id": 9, "colorHexValue":"515A5A" }, { "id": 10, "colorHexValue":"424949" } ] }, { "colorGroupName": "asphalt", "colorGroup" : [ { "id": 1, "colorHexValue":"EBEDEF" }, { "id": 2, "colorHexValue":"D6DBDF" }, { "id": 3, "colorHexValue":"AEB6BF" }, { "id": 4, "colorHexValue":"85929E" }, { "id": 5, "colorHexValue":"5D6D7E" }, { "id": 6, "colorHexValue":"34495E" }, { "id": 7, "colorHexValue":"2E4053" }, { "id": 8, "colorHexValue":"283747" }, { "id": 9, "colorHexValue":"212F3C" }, { "id": 10, "colorHexValue":"1B2631" } ] } ]
Selected hex value appears in input
Validation works as the user modifies the hex value. The user cannot enter in more than 6 characters. If the user enters any value that is NOT 3 or 6 characters long, the input will highlight in red and show a inline error message
User can enter in their own custom hex value and it will appear in the box below.
What were my contributions?
- Provided the HTML, CSS/SASS, and Angular code