How to use primeelements in Aurelia

Hi,

I would like to use the webcomponents provided by primeelements in my Aurelia application but so far, I could not figure out how to do this.

It appears that primeelements uses x-tag whereas Aurelia only provides a Polymer integration. So I am wondering if this can work at all?

I would appreciate some help. Thanks!

What have you tried?
And where does it fail?

So far, I have tried to install x-tag via jspm install npm:x-tag and primeui via jspm install npm:primeui.
I then included <require from="x-tag/dist/x-tag-core"></require> in my app.html.
In one of my templates where I wanted to use the primeelements components, I included <require from="primeui/primeelements"></require>.

On page reload I now receive the error:

Uncaught (in promise) Error: (SystemJS) Template markup must be wrapped in a <template> element e.g. <template> <!-- markup here --> </template>
	Error: Template markup must be wrapped in a <template> element e.g. <template> <!-- markup here --> </template>
	    at Object.createTemplateFromMarkup (http://localhost:9000/jspm_packages/npm/aurelia-pal-browser@1.6.0/aurelia-pal-browser.js:418:15)
	    at eval (http://localhost:9000/jspm_packages/npm/aurelia-loader-default@1.0.3/aurelia-loader-default.js:43:42)
	    at <anonymous>
	Error loading http://localhost:9000/jspm_packages/npm/x-tag@1.5.11/dist/x-tag-core.html!template-registry-entry
	    at Object.createTemplateFromMarkup (http://localhost:9000/jspm_packages/npm/aurelia-pal-browser@1.6.0/aurelia-pal-browser.js:418:15)
	    at eval (http://localhost:9000/jspm_packages/npm/aurelia-loader-default@1.0.3/aurelia-loader-default.js:43:42)
	    at <anonymous>
	Error loading http://localhost:9000/jspm_packages/npm/x-tag@1.5.11/dist/x-tag-core.html!template-registry-entry

jspm_packages/npm/x-tag@1.5.11/dist/x-tag-core.html does not exist, no idea where this loading attempt is coming from.

require in html supposes that you are trying to reference Aurelia custom element which by convention have associated views with same name but html extension
So as a first fix - move code dependencies to code

to get started you can even try to include x-tag and primeui in index.html as script tags… just to make sure that it works… and move on up from there

I tried including them as script tags as follows:

<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script src="node_modules/x-tag/dist/x-tag-core.js"></script>
<script src="node_modules/primeui/primeui.js"></script>
<script src="node_modules/primeui/primeelements.js"></script>
<script src="dist/bootstrapper.js" ></script> <!-- calls Aurelia bootstrapper -->

The problem with this is, that primeui requires jquery and jquery is loaded via SystemJS insidedist/bootstrapper.js. So primeui gets loaded too early when I do it like shown above.

I then tried to load the primeui stuff using SystemJS.

Basically, I have my template:

<template>
    <require from="primeui/primeelements"></require>
</template>

Primeelements assumes to have access to the global PUI variable defined by primeui and to the global xtag variable defined by x-tag. Thus I configured the primeelements package in SystemJS as described here:

System.config({
  ...
  packages: {
    "primeui": {
      "meta": {
        "primeelements.js": {
          "globals": {
            "PUI": "primeui/primeui",
            "xtag": "x-tag/dist/x-tag-core.js"
          }
        }
      }
    }
  },
  ...
})

This indeed results in the required globals being available when primeelements.js is invoked. However, it seems that the primeui module is not loaded beforehand. It contains jquery UI widget definitions that look like this:

(function(factory) {
    if (typeof define === 'function' && define.amd) {
      define(['jquery'], factory);
    } else if (typeof module === 'object' && module.exports) {
      module.exports = function(root, jQuery) {
        factory(jQuery);
        return jQuery;
      };
    } else {
      factory(jQuery);
    }
  }(function($) {
    $.widget("primeui.puidropdown", {
      // ....
    });
}));

For the above module, module.exports is called but then the module is never instantiated via the factory method. Thus, the widget is never defined which causes following error when the webcomponent tags are processed by x-tag:

Uncaught TypeError: this.xtag.select.puidropdown is not a function
    at HTMLElement.created (primeelements.js:1096)
    at HTMLElement.value [as createdCallback] (x-tag-core.js:3837)
    at ViewFactory.create (aurelia-templating.js:2406)
    at HtmlBehaviorResource.create (aurelia-templating.js:4114)
    at eval (router-view.js:129)
    at <anonymous>

this.xtag.select is a jQuery object.

It feels like I am almost there… Unfortunately I’m not an expert with this whole SystemJS and module loading stuff. So I hope you can help!

Sounds like you need to shim primeelements to make sure to define its dependencies. Take a look here at the shim section https://github.com/jspm/registry/wiki/Configuring-Packages-for-jspm

1 Like

Ok, I tried to shim primeelements according to explanations on github as follows, no idea if that is right:

System.config({
  ...
  packages: {
    "primeui": {
      "meta": {
        "primeelements.js": {
          "globals": {
            "PUI": "primeui/primeui",
            "xtag": "x-tag/dist/x-tag-core.js"
          }
        }
      }
    }
  },
  meta: {
    "npm:primeui@4.1.15/primeelements.js": {
      "deps": ['npm:primeui@4.1.15/primeui.js', 'npm:x-tag@1.5.11/dist/x-tag-core.js'],
      "format": "global"
    }
  }, ...

However, this seems to have no effect - same problem as before. I also tried to extend this with

meta: {
    "npm:primeui@4.1.15/primeelements.js": {
      "deps": ['npm:primeui@4.1.15/primeui.js', 'npm:x-tag@1.5.11/dist/x-tag-core.js'],
      "format": "global"
    },
    "npm:primeui@4.1.15/primeui.js": {
      "format": "global"
    }
}

This gives the error

    ERROR [app-router] Error: (SystemJS) require is not a function
	TypeError: require is not a function
	    at eval (http://localhost:9000/jspm_packages/npm/primeui@4.1.15/primeui.js:11349:4)
	    at eval (<anonymous>)
	Evaluating http://localhost:9000/jspm_packages/npm/primeui@4.1.15/primeui.js
	Error loading http://localhost:9000/jspm_packages/npm/primeui@4.1.15/primeelements.js
	    at eval (http://localhost:9000/jspm_packages/npm/primeui@4.1.15/primeui.js:11349:4)
	    at eval (<anonymous>)
	Evaluating http://localhost:9000/jspm_packages/npm/primeui@4.1.15/primeui.js
	Error loading http://localhost:9000/jspm_packages/npm/primeui@4.1.15/primeelements.js

Also, addings deps to the package definition has no effect:

System.config({
  ...
  packages: {
    "primeui": {
      "meta": {
        "primeelements.js": {
          "globals": {
            "PUI": "primeui/primeui",
            "xtag": "x-tag/dist/x-tag-core.js"
          },
          "deps": [
            "primeui/primeui",
            "jquery-ui"
          ]
        }
      }
    }
  },
  meta: {
    "npm:primeui@4.1.15/primeelements.js": {
      "deps": ['npm:primeui@4.1.15/primeui.js', 'npm:x-tag@1.5.11/dist/x-tag-core.js'],
      "format": "global"
    }
  }, ...

Can you create a sample with what you’ve been trying so we can fiddle around?

I have created a sample project based on skeleton-navigation that contains my work so far. Sadly, I cannot upload zip files here so I have uploaded it here: https://we.tl/SDP1v8ZLT9
I included a simple primeelements component on the welcome screen so you should see the error message as soon as you load the page.
Thanks a lot for all your help so far!!

I get a totally different error being:
this.xtag.select.puidropdown is not a function

so it seems like the setup is ok but either the library itself has a bug or something changed in the meantime. Found this Plunker and SO question related

And here an official request to their forums:
https://forum.primefaces.org/viewtopic.php?f=16&p=165030

This is exactly the error that I mentioned in one of my previous answers.

I got the same version of primeelements working using script tags in a different app without Aurelia or SystemJS. As I said, this.xtag.selectis a jQuery object. puidropdown is a function that would normally be registered with jQuery via the invocation of $.widget("primeui.puidropdown", {...}) in primeui.js. Since this code is never invoked, the function is not registered, hence the error. The reason why it is not invoked must have to do with module loading.

So maybe adding jquery and not only xtags as dependencies solves that

No, the absence of jquery is not the issue (yet). The error that is produced in the sample project is because none of the factory methods in primeui.js containing the widget definitions are invoked.
The code that is currently invoked in primeui.js merely exports the factory function for the widget:

module.exports = function(root, jQuery) {
        factory(jQuery);
        return jQuery;
      };

The key to getting this to work is to find a way to trigger the invocation of this exported function. I guess I would need to import this somewhere and somehow but how?

it is the default export, I guess…
so either require('smthn')()
or

import * as fff from 'smthn'
fff()

I might be wrong with exact syntax but idea is that you import module and execute the returned value

I think this is exactly what the linked SO issue is talking about

1 Like

I now changed my main.ts to the following:

import 'bootstrap';
import {Aurelia} from 'aurelia-framework';
import * as $ from 'jquery';
import * as primeui from 'primeui';

export function configure(aurelia: Aurelia) {
  aurelia.use
    .standardConfiguration()
    .developmentLogging();

  primeui(null, $);

  aurelia.start().then(() => aurelia.setRoot());
}

This appears to go in the right direction but now I get the following error:

ERROR [app-router] Error: (SystemJS) require is not a function
	TypeError: require is not a function
	    at eval (http://localhost:9000/jspm_packages/npm/primeui@4.1.15/primeui.js:11349:4)
	    at eval (<anonymous>)
	    at r (http://localhost:9000/jspm_packages/npm/bluebird@3.4.1/js/browser/bluebird.min.js:33:7722)
	    at i._settlePromiseFromHandler (http://localhost:9000/jspm_packages/npm/bluebird@3.4.1/js/browser/bluebird.min.js:32:13044)
	    at i._settlePromise (http://localhost:9000/jspm_packages/npm/bluebird@3.4.1/js/browser/bluebird.min.js:32:13847)
	Evaluating http://localhost:9000/jspm_packages/npm/primeui@4.1.15/primeui.js
	Error loading http://localhost:9000/jspm_packages/npm/primeui@4.1.15/primeelements.js
	    at eval (http://localhost:9000/jspm_packages/npm/primeui@4.1.15/primeui.js:11349:4)
	    at eval (<anonymous>)
	    at r (http://localhost:9000/jspm_packages/npm/bluebird@3.4.1/js/browser/bluebird.min.js:33:7722)
	    at i._settlePromiseFromHandler (http://localhost:9000/jspm_packages/npm/bluebird@3.4.1/js/browser/bluebird.min.js:32:13044)
	    at i._settlePromise (http://localhost:9000/jspm_packages/npm/bluebird@3.4.1/js/browser/bluebird.min.js:32:13847)
	Evaluating http://localhost:9000/jspm_packages/npm/primeui@4.1.15/primeui.js
	Error loading http://localhost:9000/jspm_packages/npm/primeui@4.1.15/primeelements.js

Sounds like it picked up the wrong Module Format. But since you’ve shimmed it as global cant you access that directly from window and initialize it that way?

The format of primeui.js seems to be “cjs” - at least that is written at the beginning of the file. How would I access this from window? At least window.primeui is undefined…

As far as I remember your shim you defined the global as PUI in config.js right?

Thanks, I managed to go one step further ^^

Using:

import 'bootstrap';
import {Aurelia} from 'aurelia-framework';
import * as $ from 'jquery';

export function configure(aurelia: Aurelia) {
  aurelia.use
    .standardConfiguration()
    .developmentLogging();

  System.import('primeui').then(function (primeui) { 
	primeui(null, $);
  }).then(function() {
	aurelia.start().then(() => aurelia.setRoot());
  });  
}

I managed to load and invoke the primeui factory - but only the last one!
I also know why:
primeui.js is built up like this:

"format cjs";
(function(process) {
  // widget puitree
  (function(factory) {
    if (typeof define === 'function' && define.amd) {
      define(['jquery'], factory);
    } else if (typeof module === 'object' && module.exports) {
      module.exports = function(root, jQuery) {
        factory(jQuery);
        return jQuery;
      };
    } else {
      factory(jQuery);
    }
  }(function($) {
    $.widget("primeui.puitree", {
    ...
  }));
  // widget puitreetable
  (function(factory) {
    if (typeof define === 'function' && define.amd) {
      define(['jquery'], factory);
    } else if (typeof module === 'object' && module.exports) {
      module.exports = function(root, jQuery) {
        factory(jQuery);
        return jQuery;
      };
    } else {
      factory(jQuery);
    }
  }(function($) {
    $.widget("primeui.puitreetable", {
    ....
  }));
})(require('process'));

As you can see, there is one widget factory after the other. At the time of module loading, the

module.exports = <factory-method>

are executed sequentially from top to bottom. So each factory definition overwrites the module.export of its predecessor and so the last definition wins. I have no idea how this is supposed to work.

Any ideas?