1

I'm working on a website based on the latest Angular 8 version and I need to implement a Ecwid e-shop page on one of my components with the following code generated by Ecwid:

<div id="my-store-24629028"></div>
<div>
  <script
    data-cfasync="false"
    type="text/javascript"
    src="https://app.ecwid.com/script.js?24629028&data_platform=code&data_date=2020-02-17"
    charset="utf-8"
  ></script>
  <script type="text/javascript">
    xProductBrowser(
      'categoriesPerRow=3',
      'views=grid(20,3) list(60) table(60)',
      'categoryView=grid',
      'searchView=list',
      'id=my-store-24629028',
    );
  </script>
</div>

Angular generates the component and the <div id="my-store-24629028"></div> section but none of the scripts is rendered.. and so my e-shop page isn't rendered. From what I could find online it's a design choice from the Angular Team but isn't there any option or solution to disable this ?

The closest solution for the first script I've found is this stackoverflow thread but I don't see how to handle the second script tag Ecwid generates..

UPDATE

TS File:

import { Component, Renderer2, OnInit, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Component({
  selector: 'app-shop',
  templateUrl: './shop.component.html',
  styleUrls: ['./shop.component.scss'],
})
export class ShopComponent implements OnInit {
  constructor(private renderer2: Renderer2, @Inject(DOCUMENT) private document: Document) {}

  public ngOnInit() {
    const script = this.renderer2.createElement('script');
    script.type = `text/javascript`;
    script.src = 'https://app.ecwid.com/script.js?24629028&data_platform=code&data_date=2020-02-17';

    const script2 = this.renderer2.createElement('script');
    script2.type = `text/javascript`;
    script2.text = `
      xProductBrowser(
        'categoriesPerRow=3',
        'views=grid(20,3) list(60) table(60)',
        'categoryView=grid',
        'searchView=list',
        'id=my-store-24629028',
      );
        `;

    this.renderer2.appendChild(this.document.getElementById('toto'), script);
    this.renderer2.appendChild(this.document.getElementById('toto'), script2);
  }
}

After following @Supporterino advices I managed to inject both scripts on the HTML sadly I'm now facing a variable not defined error:

Uncaught ReferenceError: xProductBrowser is not defined
    at <anonymous>:2:7
    at EmulatedEncapsulationDomRenderer2.push../node_modules/@angular/platform-browser/fesm5/platform-browser.js.DefaultDomRenderer2.appendChild (platform-browser.js:1100)
    at DebugRenderer2.push../node_modules/@angular/core/fesm5/core.js.DebugRenderer2.appendChild (core.js:30407)
    at ShopComponent.push../src/app/pages/shop/shop.component.ts.ShopComponent.ngOnInit (shop.component.ts:30)
    at checkAndUpdateDirectiveInline (core.js:21096)
    at checkAndUpdateNodeInline (core.js:29494)
    at checkAndUpdateNode (core.js:29456)
    at debugCheckAndUpdateNode (core.js:30090)
    at debugCheckDirectivesFn (core.js:30050)
    at Object.eval [as updateDirectives] (ShopComponent_Host.ngfactory.js? [sm]:1)

SOLUTION

So after a few hours trying to handle the script loading @juvs anwser helped getting this implementation to finally work !

Final TS File

import { Component, Renderer2, OnInit, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Component({
  selector: 'app-shop',
  templateUrl: './shop.component.html',
  styleUrls: ['./shop.component.scss'],
})
export class ShopComponent implements OnInit {
  constructor(private renderer2: Renderer2, @Inject(DOCUMENT) private document: Document) {}

  public ngOnInit() {
    const storeId = 24629028;
    const script = this.renderer2.createElement('script');
    script.setAttribute('type', 'text/javascript');
    script.setAttribute('charset', 'utf-8');
    script.setAttribute('data-cfasync', 'false');
    script.setAttribute('src', `https://app.ecwid.com/script.js?${storeId}&data_platform=code&data_date=2020-02-17`);
    script.onload = this.injectEcwidProductBrowser(storeId);

    this.renderer2.appendChild(this.document.getElementById('ecwidScriptsSection'), script);
  }

  private injectEcwidProductBrowser(storeId) {
    return () => {
      const ecwidBrowserScript = document.createElement('script');
      ecwidBrowserScript.setAttribute('type', 'text/javascript');
      ecwidBrowserScript.setAttribute('charset', 'utf-8');
      ecwidBrowserScript.text = `xProductBrowser("categoriesPerRow=3","views=grid(20,3) list(60) table(60)","categoryView=grid","searchView=list","id=my-store-${storeId}");`;
      document.head.appendChild(ecwidBrowserScript);
    };
  }
}

Final HTML File

<div id="my-store-24629028"></div>
<div id="ecwidScriptsSection"></div>

Hope this helps someone in the future cause as of right now there's actually not that much information around, even Ecwid support say they don't support Angular2 & AngularJS ..

3 Answers 3

3

You should init the Ecwid widget after script.js is loaded.

Example:

export class AppComponent implements OnInit {
  constructor(
    private _renderer2: Renderer2,
    @Inject(DOCUMENT) private _document: Document
  ) {}

  public ngOnInit() {
    let storeId = 24629028;
    let script = this._renderer2.createElement("script");
    script.setAttribute("type", "text/javascript");
    script.setAttribute("charset", "utf-8");
    script.setAttribute("data-cfasync", "false");
    script.setAttribute(
      "src",
      `https://app.ecwid.com/script.js?${storeId}&data_platform=code&data_date=2020-02-17`
    );
    script.onload = this.injectEcwidProductBrowser(storeId);

    this._renderer2.appendChild(this._document.body, script);
  }

  private injectEcwidProductBrowser(storeId) {
    return function() {
      const ecwidBrowserScript = document.createElement("script");
      ecwidBrowserScript.setAttribute("type", "text/javascript");
      ecwidBrowserScript.setAttribute("charset", "utf-8");
      ecwidBrowserScript.text = `xProductBrowser("categoriesPerRow=3","views=grid(20,3) list(60) table(60)","categoryView=grid","searchView=list","id=my-store-${storeId}");`;
      document.head.appendChild(ecwidBrowserScript);
    };
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Jesus! Thanks this worked was struggling to handle the scripts loading part :)
0

You could take a look at this answer https://stackoverflow.com/a/43559644/11193058 which describes how to work around the removable of the script tag and use this method to inject your javascript code.

3 Comments

I managed to adapt my TS file and get both scripts to show on the DOM. But the second script still errors: "Uncaught ReferenceError: xProductBrowser is not defined"
@HelderNorte Sounds like the js file referenced in the first script isn't loaded right. You could check if the js file is present with the developer console of chrome. And the script tag injection of the js file should go first that you could check as well.
Thanks with your help and the anwser of @juvs I managed to get it working will update the post soon :)
0

That's how to implement this in TS file:

<div style="text-align: center;">
<script type="text/java script" language="java script">
    var ANS_customer_id = "ff";
</script>
<script type="text/java script" language="java script" src="https://verify.authorize.net:443/seal/seal.js">
</script></div>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.