0

https://codepen.io/tuckermassad/pen/rPYNLq

I copied the CSS doodle code from there into my angular component:

<section class="main">
    <css-doodle grid="5">
        :doodle {
          @grid: 10 / 100%; 
        }
        background: @pick(
          #ff0198, #8156a8, #ff6d00, #ff75e4
        );

        transform: translate(
          @rand(-50vw, 50vw),
          @rand(-50vh, 50vh)
        );

        @size: 3.5vmin;
        @shape: heart;
        @place-cell: 50% 50%;

        animation-name: explosion;
        animation-iteration-count: infinite;
        animation-direction: reverse;
        animation-duration: calc(@rand(2s, 5s, .1));
        animation-delay: calc(@rand(-5s, -1s, .1));
        animation-timing-function: 
          cubic-bezier(.84, .02, 1, 1);

        @keyframes explosion {
          0% { opacity: 0; }
          70% { opacity: 1; }
          100% { transform: translate(0, 0); }
        }
      </css-doodle>
</section>

Now, I Installed css-doodle with npm i css-doodle, and I ran the project and I get the following error:

compiler.js:2547 Uncaught Error: Template parse errors:
Unexpected character "EOF" (Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.) ("
        }
      </css-doodle>
</section>[ERROR ->]"): ng:///AppModule/HomeComponent.html@32:10
Invalid ICU message. Missing '}'. ("
        }
        background: @pick(
          #ff0198, #8156a8, [ERROR ->]#ff6d00, #ff75e4
        );

"): ng:///AppModule/HomeComponent.html@6:28
Invalid ICU message. Missing '}'. ("
        }
      </css-doodle>
</section>[ERROR ->]"): ng:///AppModule/HomeComponent.html@32:10

Is there a way to work with css doodle in angular?

zgue
  • 3,793
  • 9
  • 34
  • 39
Ben Beri
  • 1,101
  • 4
  • 23
  • 64

3 Answers3

2

To get this library to work with Angular, there are a few steps you have to take.

npm install css-doodle --save

The following steps I did in the default app created by the cli, you will have to update them to make sure that everything is done in the correct module/components for your project.

app.component.html

<section class="main">
  <css-doodle grid="5">
    {{'
      :doodle {
        @grid: 10 / 100%;
      }
      background: @pick(
        #ff0198, #8156a8, #ff6d00, #ff75e4
      );

      transform: translate(
        @rand(-50vw, 50vw),
        @rand(-50vh, 50vh)
      );

      @size: 3.5vmin;
      @shape: heart;
      @place-cell: 50% 50%;

      animation-name: explosion;
      animation-iteration-count: infinite;
      animation-direction: reverse;
      animation-duration: calc(@rand(2s, 5s, .1));
      animation-delay: calc(@rand(-5s, -1s, .1));
      animation-timing-function:
        cubic-bezier(.84, .02, 1, 1);

      @keyframes explosion {
        0% { opacity: 0; }
        70% { opacity: 1; }
        100% { transform: translate(0, 0); }
      }
      '}}
    </css-doodle>
</section>

As you can see above(and listed in the error you posted), { is a special character in Angular and if you want to use it in a view it has to be escaped properly. As you can see the whole css block is encased in {{''}} in order to do that escaping.

Once you do that though, you will get another error relating to the fact that you are using a custom HTML element that Angular doesn't know about. In order to fix that, you have to go into your module and add schemas: [CUSTOM_ELEMENTS_SCHEMA] to your module.

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule { }

After that, there is one more step. Now you won't receive any errors from Angular, but your component won't render as expected. That is because Angular isn't loading the javascript file installed with your npm install above. There are multiple ways to fix this. The easiest approach that I took for the proof-of-concept was to import that npm module into the component with import 'css-doodle';.

app.component.ts

import { Component } from '@angular/core';
import 'css-doodle';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  title = 'ng-css-doodle';
}

Full GitHub repo example

peinearydevelopment
  • 11,042
  • 5
  • 48
  • 76
  • I tried your solution in [this stackblitz](https://stackblitz.com/edit/angular-rvf8rg?file=src%2Fapp%2Fapp.component.html) and it works. – ConnorsFan Feb 23 '19 at 15:57
  • @ConnorsFan your stackblitz app throws "'customElements' is not defined" – zgue Mar 19 '19 at 08:49
  • @zgue - I removed one useless `allo` variable from the stackblitz. I don't see the error that you mention, however. – ConnorsFan Mar 19 '19 at 12:07
  • @ConnorsFan your are right, it works fine. Maybe I tried it with the wrong browser. – zgue Mar 19 '19 at 13:27
0

There is another way to avoid such error by using the use attribute, which lets you write rules in normal CSS files: https://css-doodle.com/#property-@use

For Example:

<style>
  css-doodle {
    --rule: (
      :doodle {
        @grid: 10 / 100%;
      }
      background: @pick(
        #ff0198, #8156a8, #ff6d00, #ff75e4
      );

      transform: translate(
        @rand(-50vw, 50vw),
        @rand(-50vh, 50vh)
      );

      @size: 3.5vmin;
      @shape: heart;
      @place-cell: 50% 50%;

      animation-name: explosion;
      animation-iteration-count: infinite;
      animation-direction: reverse;
      animation-duration: calc(@rand(2s, 5s, .1));
      animation-delay: calc(@rand(-5s, -1s, .1));
      animation-timing-function:
        cubic-bezier(.84, .02, 1, 1);

      @keyframes explosion {
        0% { opacity: 0; }
        70% { opacity: 1; }
        100% { transform: translate(0, 0); }
      }
    );
  }
</style>

<css-doodle use="var(--rule)"></css-doodle>


See demo here:
https://codepen.io/yuanchuan/pen/a07d7bebf04b35b9752e31e970ecd68c

yuanchuan
  • 56
  • 4
0

using quotes inside interpolation {{''}} was not working for me plus that approach is not much readable and dynamic, although using stylings rule helped but that approach is more static approach and again, i couldn't generate values dynamically. I followed the JS API update method and that worked perfectly.

Now i can wrap this code inside a component, accepting rules as @Input property, exporting other apis as component methods and now this component can be shared and reused.

  ngAfterViewInit() {
    this.initDoodle();
  }

  initDoodle() {
    /* you can add typing in your code to avoid use of any */
    const doodle = document.querySelector('css-doodle') as any; 

    /* update styles and refresh */
    doodle.update(`
      @grid: 10 / 100vw 100vh;
      :doodle {
        background-color: #182F53;
      }

      transition: .2s @r(.6s);
      border-radius: @r(100%);
      will-change: transform;
      transform: scale(@r(.15, 1.25));

      background: hsla(calc(240 - 6 * @row * @col), 70%, 68%, @r1);
    `);

    /* just refresh */
    doodle.update();
  }

 
Nutan Gwari
  • 205
  • 4
  • 9