8

I was creating an app using angular 2, bootstrap 4 and I found out that glyphicons were dropped, so I have decided to use Octicon as suggested,

I did npm install --save octicons

After that I didn't under stand a thing. I thought i have to include octicons.css only but that didn't work.

It only contains

.octicon {
  display: inline-block;
  vertical-align: text-top;
  fill: currentColor;
}

What is a simple step bu step way to use Octicon?

svarog
  • 9,477
  • 4
  • 61
  • 77
Dinkar Thakur
  • 3,025
  • 5
  • 23
  • 35

3 Answers3

15

This gets you actual SVG tags easily reusable in your Angular app. Credit goes to robisim74 on GitHub, but posting here since this was a high Google result when I was trying to figure it out.

  1. npm install --save octicons

  2. In your .angular-cli.json file under styles:

    "../node_modules/octicons/build/build.css",

  3. Build a directive that you pass the icon's name to (searchable at https://octicons.github.com/). This is one way to do it, but look through the logic and you can imagine doing it other ways if it made sense to for your app. You'd probably make this directive within your SharedModule and import SharedModule into whatever feature modules you want to use it.

import { Directive, Input, OnInit, ElementRef, Renderer2 } from '@angular/core';

import * as octicons from 'octicons';

@Directive({
    selector: '[octicon]'
})
export class OcticonDirective implements OnInit {

    @Input() octicon: string;
    @Input() color: string;
    @Input() width: number;

    constructor(private elementRef: ElementRef, private renderer: Renderer2) { }

    ngOnInit(): void {
        const el: HTMLElement = this.elementRef.nativeElement;
        el.innerHTML = octicons[this.octicon].toSVG();

        const icon: Node = el.firstChild;
        if (this.color) {
            this.renderer.setStyle(icon, 'fill', this.color);
        }
        if (this.width) {
            this.renderer.setStyle(icon, 'width', this.width);
            this.renderer.setStyle(icon, 'height', '100%');
        }
    }

}
  1. Then in your template, some example usages:

    <span octicon="gear"></span>

    <span octicon="gear" color="red" width="32"></span>

jmq
  • 2,359
  • 18
  • 32
  • 1
    Btw, 'color' should be changed to 'fill' – MK_Dev Jan 09 '20 at 05:54
  • Thanks. Just a pair of comments on more recent angular versions (tested in v9): [2] Add `@import '~octicons/build/build.css';` to `src/styles.css` and [3] the selector should be `appOcticon` (e.g. ``). – danidelvalle Apr 18 '20 at 16:03
2

It isn't as easy as adding a CSS file as you have found out. After you do npm install --save octicons though, if you navigate to the following folder

node_modules/octicons/build/

you will find a file named sprite.octicons-demo.html which, if you open it, shows you what you need to do. Basically, the only thing you need to do to make this work is open up that file, copy the <svg>...</svg> tag, paste it into your index.html and then access the icons like so

<svg version="1.1" width="32" height="32" viewBox="0 0 16 16" class="octicon octicon-alert" aria-hidden="true"><use xlink:href="#alert" /></svg>

Much of this is included on the man page so you may want to go back and read it. You should definitely take a look at the articles it links to on CSS-Tricks

UPDATE

I wanted to come back to this as I wrote the above answer pretty hastily. While the above solution will work, it is a pretty 'dirty' solution IMHO. One of the biggest drawbacks with putting the SVG tag directly into your document is that it gets rendered as a large empty block level element. Of course you can hack around this by wrapping the <svg></svg> tag in something like <div style="display:none;"><svg>...</svg></div> but, again, that is pretty dirty (not to mention all of that inline SVG cluttering up your source).

Instead, I find that it is much more straightforward to treat the SVG icons like you would any other image. If you followed the directions above, remove the <svg>...</svg> block from your index.html file and then go to your template where you are displaying the icon and replace your current markup with the following

<svg width="32" height="32" class="octicon" aria-hidden="true"><use xlink:href="/node_modules/octicons/build/sprite.octicons.svg#alert" /></svg>

You should then see the alert icon displayed as a 32x32 image. The two differences here are that you are providing a relative path to the svg file in addition to specifying which element you want and you aren't defining the viewBox. Again, CSS-Tricks has a pretty good article that explains the difference between using g and symbol to define SVG icons; that article makes it clear why we don't need to define viewBox on our inline element.

dparsons
  • 2,812
  • 5
  • 28
  • 44
1

You can import Octicon in Typescript:

import { calendar } from 'octicons';

export class MyComponent implements OnInit {

  public calendarIcon: SafeHtml;

  constructor(private sanitizer: DomSanitizer) { }

  ngOnInit() {
    this.calendarIcon = this.sanitizer.bypassSecurityTrustHtml(calendar.toSVG());
  }

}

Then you can use it as innerHTML:

<div [innerHTML]="calendarIcon">

You can write pipe for sanitization - see Angular 2, DomSanitizer, bypassSecurityTrustHtml, SVG.

sax
  • 808
  • 1
  • 12
  • 25