angularzk

How to preserve XHTML attributes case during `ng build`?


I'm trying to integrate an Angular 12 app into a ZK application.

Here is my index.zhtml:

<?xml version="1.0"?>
<!DOCTYPE html>
<html xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:z="zul" xmlns="native" lang="fr">
  <head>
    <meta charset="utf-8">
    <title>ZK + Angular 12</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" type="image/x-icon" href="favicon.ico">
  </head>
  <body>
    <z:div
      apply="org.zkoss.bind.BindComposer"
      viewModel="@id('vm')@init('com.c4_soft.zk_angular_demo.MyViewModel')"
      validationMessages="@id('vmsgs')">
        ...
        <z:button label="ZK ++" onClick="@command('cmd')"></z:button>
    </z:div>
    <app-root></app-root>
  </body>
</html>

My problem (actually, the first one, I anticipate quite a few others): attributes in "zul" namespace are case sensitive (z:div viewModel and z:button onClick for instance) but ng build transforms it to lower-case.

How to prevent ng build from processing attributes case for xml tags in namespaces it doesn't know about?


Solution

  • Since I am from the ZK side I don't actually know whether there is a compiler flag/switch do disable the automatic lower casing.

    I think angular is trying to compile too much here. zhtml/zul-files are ZK specific formats and need to be parsed/executed by ZK's DHtmlLayoutServlet at server side at runtime. If you process these files with ng build it looks like this compiler is unaware of ZK's syntax and changes/breaks things according to it's own conventions defaults (internally angular uses the parse5 html parser which deliberately switches all tag/attribute names to lowercase)

    Bottom line: you can't compile zhtml/zul files with ng build.

    Instead what can do is to compile your angular application into JS and then include it into the zhtml page using a script tag.

    <?xml version="1.0"?>
    <!DOCTYPE html>
    <html xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:z="zul" xmlns="native" lang="fr">
      <head>
        <meta charset="utf-8">
        <title>ZK + Angular 12</title>
        <script>document.write('<base href="' + document.location + '" />');</script>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="icon" type="image/x-icon" href="favicon.ico">
    
        <script src="yourlibs.js"></script>
        <script src="morelibs.js"></script>
        <script>/*script initializing app-root*/</script>
    
      </head>
      <body>
        <z:div
          apply="org.zkoss.bind.BindComposer"
          viewModel="@id('vm')@init('com.c4_soft.zk_angular_demo.MyViewModel')"
          validationMessages="@id('vmsgs')">
            ...
            <z:button label="ZK ++" onClick="@command('cmd')"></z:button>
        </z:div>
        <app-root></app-root>
      </body>
    </html>
    

    Here a few links to existing integration examples based on angular 2 and 8:

    In both cases the JS files are added explicitly to the zhtml/zul files independent of the actual build process.

    https://github.com/zkoss-demo/zkangular2/blob/master/src/main/webapp/hero/index.zhtml

    https://github.com/zkoss-demo/client-binding-demo-angular/blob/master/src/main/resources/web/hello.zul

    The above is for ZK being the main application and allows adding nested angular components/pages.

    If you want your angular app to be the main app then you might look into zk-embedded, which provides a JS api to integrate zul pages into arbitrary html pages ()