diff --git a/packages/provider/assets/index.html.ejs b/packages/provider/assets/index.html.ejs
index 0ce3cd32969d7f75e3c52ea6e9ae8b763bb6c83b..3d35a5f69accc3305eae3ac28c870d9bf881eb7f 100644
--- a/packages/provider/assets/index.html.ejs
+++ b/packages/provider/assets/index.html.ejs
@@ -2,6 +2,7 @@
 <html>
 <head>
     <meta charset="UTF-8">
+    <script type="module" src="dbp-provider.js"></script>
     <script type="module" src="dbp-provider-demo.js"></script>
     <!--
         This is for debugging only:
@@ -9,16 +10,18 @@
         -  unhandled requests are logged in the console
     -->
     <script>
-        window.addEventListener('inherit', e => console.log('window eventListener("inherit",..) name "' + e.detail.name + '" not found.'));
         window.addEventListener('subscribe', e => console.log('window eventListener("subscribe",..) name "' + e.detail.name + '" not found.'));
         window.addEventListener('unsubscribe', e => console.log('window eventListener("unsubscribe",..) name "' + e.detail.name + '" not found.'));
     </script>
+    <style>
+        body { padding: 50px;}
+    </style>
 </head>
 
 <body>
-
-<dbp-provider-demo lang="de"></dbp-provider-demo>
-
-<p>version: <span style="color: white; background-color: black;"><%= buildInfo.info %></span></p>
+    <dbp-provider id="root" root="1" availability="global" lang="de">
+        <dbp-provider-demo id="provider-demo" subscribe="lang:lang"></dbp-provider-demo>
+    </dbp-provider>
+    <p>version: <span style="color: white; background-color: black;"><%= buildInfo.info %></span></p>
 </body>
 </html>
diff --git a/packages/provider/src/dbp-provider-demo.js b/packages/provider/src/dbp-provider-demo.js
index 0c63c30c11bd21ce582fcf45bf04a78620ad2def..10a482fb5cdd9e3a17597528f42c178824cf6e85 100644
--- a/packages/provider/src/dbp-provider-demo.js
+++ b/packages/provider/src/dbp-provider-demo.js
@@ -1,13 +1,15 @@
 import {i18n} from './i18n.js';
-import {css, html, LitElement} from 'lit-element';
+import {css, html} from 'lit-element';
 import {ScopedElementsMixin} from '@open-wc/scoped-elements';
 import {AuthKeycloak, LoginButton} from '@dbp-toolkit/auth';
 import * as commonUtils from '@dbp-toolkit/common/utils';
 import * as commonStyles from '@dbp-toolkit/common/styles';
 import {Provider} from '@dbp-toolkit/provider';
+import {LanguageSelect} from '@dbp-toolkit/language-select';
+import DBPLitElement from "@dbp-toolkit/common/dbp-lit-element";
 
 
-class ProviderDemo extends ScopedElementsMixin(LitElement) {
+class ProviderDemo extends ScopedElementsMixin(DBPLitElement) {
 
     constructor() {
         super();
@@ -18,6 +20,7 @@ class ProviderDemo extends ScopedElementsMixin(LitElement) {
         return {
             'dbp-auth-keycloak': AuthKeycloak,
             'dbp-login-button': LoginButton,
+            'dbp-language-select': LanguageSelect,
             'dbp-provider': Provider,
             'dbp-consumer': DemoConsumer,
         };
@@ -25,6 +28,7 @@ class ProviderDemo extends ScopedElementsMixin(LitElement) {
 
     static get properties() {
         return {
+            ...super.properties,
             lang: { type: String },
         };
     }
@@ -32,6 +36,20 @@ class ProviderDemo extends ScopedElementsMixin(LitElement) {
     connectedCallback() {
         super.connectedCallback();
         i18n.changeLanguage(this.lang);
+
+    }
+
+    attributeChangedCallback(name, oldValue, newValue) {
+        console.log('ProviderDemo (' + this.id + ') attributeChangesCallback( ' + name + ', ' + oldValue + ', ' + newValue + ')');
+        switch(name) {
+            case 'lang':
+                this.lang = newValue;
+                i18n.changeLanguage(this.lang);
+                break;
+            default:
+                super.attributeChangedCallback(name, oldValue, newValue);
+        }
+        this.render();
     }
 
     static get styles() {
@@ -46,71 +64,52 @@ class ProviderDemo extends ScopedElementsMixin(LitElement) {
         ];
     }
 
+    get id() {
+        return this.getAttribute('id');
+    }
+
     render() {
         return html`
             <section class="section">
-                <p>Provider <em>"root"</em> is the top most in hierarchy:</p>
-                <dbp-provider id="root"
-                              init="availability=global"
-                ></dbp-provider>
-<pre>
-&lt;dbp-provider  id="root"  init="availability=global" &gt;&lt;/dbp-provider&gt;
-</pre>
+                <p>${i18n.t('demo.provider_description', {id: "root", description: "is the top most in hierarchy"})}</p>
+                <pre>&lt;dbp-provider  id="root"  root="1" availability="global" >&lt;/dbp-provider&gt;</pre>
                 <div class="container">
-                    <h1 class="title">Provider-Demo</h1>
+                    <h1 class="title">${i18n.t('demo.provider')}-Demo</h1>
                 </div>
                 <div class="container">
                     <dbp-auth-keycloak lang="${this.lang}" url="https://auth-dev.tugraz.at/auth" realm="tugraz" client-id="auth-dev-mw-frontend-local" load-person try-login></dbp-auth-keycloak>
                     <dbp-login-button lang="${this.lang}" show-image></dbp-login-button>
+                    <dbp-language-select></dbp-language-select>
                 </div>
-                <div class="container">
-                    <h2>Provider</h2>
-                    <p>Provider <em>"demo"</em> has only <em>border-color</em> to offer:</p>
-                    <dbp-provider id="demo"
-                                  init="bc=blue"
-                    ></dbp-provider>
-<pre>
-&lt;dbp-provider  id="demo"  init="bc=blue" &gt;&lt;/dbp-provider&gt;
-</pre>
-                    <p>Provider <em>"foo-bar"</em> has some values in its store:</p>
+                <dbp-provider id="demo"
+                              bc="blue">
                     <dbp-provider id="foo-bar"
-                                  init="foo=9,bar=20"
-                    ></dbp-provider>
-<pre>
-&lt;dbp-provider  id="foo-bar"  init="foo=9,bar=20" &gt;&lt;/dbp-provider&gt;
-</pre>
-                    <h2>Consumer</h2>
-                    <p>Consumer <em>"c1"</em> will only subscribe to <em>border-color</em></p>
-<pre>
-&lt;dbp-consumer  id="c1"  subscribe="bc:border-color" &gt;&lt;/dbp-consumer&gt;
-</pre>
-                    <dbp-consumer id="c1"
-                                  subscribe="bc:border-color"
-                    ></dbp-consumer>
-                    <p>Consumer <em>"c2"</em> subscribes to <em>foo</em></p>
-<pre>
-&lt;dbp-consumer  id="c2"  subscribe="foo:foo" &gt;&lt;/dbp-consumer&gt;
-</pre>
-                    <dbp-consumer id="c2"
-                                  subscribe="foo:foo"
-                    ></dbp-consumer>
-                    <p>Consumer <em>"c3"</em> subscribes for <em>status</em> which is provided as <em>availability</em></p>
-<pre>
-&lt;dbp-consumer  id="c3"  subscribe="availability:status"  border-color="orange" &gt;&lt;/dbp-consumer&gt;
-</pre>
-                    <dbp-consumer id="c3"
-                                  subscribe="availability:status"
-                                  border-color="orange"
-                    ></dbp-consumer>
-                    <p>Consumer <em>"c4"</em> subscribes for <em>status</em> which is provided as <em>unknown-name</em> which does not exist...</p>
-<pre>
-&lt;dbp-consumer  id="c4"  subscribe="unknown-name:status"  border-color="darkgray" &gt;&lt;/dbp-consumer&gt;
-</pre>
-                    <dbp-consumer id="c4"
-                                  subscribe="unknown-name:status"
-                                  border-color="darkgray"
-                    ></dbp-consumer>
-                </div>
+                                  foo="9"
+                                  bar="20">
+                        <div class="container">
+                            <h2>${i18n.t('demo.provider')}</h2>
+                            <p>${i18n.t('demo.provider_description', {id: "demo", description: "has only \"border-color\" to offer"})}</p>                            <pre>&lt;dbp-provider  id="demo"  bc="blue" &gt;&lt;/dbp-provider&gt;</pre>
+                            <p>${i18n.t('demo.provider_description', {id: "foo-bar", description: "has some values in its store"})}</p>
+                            <pre>&lt;dbp-provider  id="foo-bar"  foo="9" bar="20" &gt;&lt;/dbp-provider&gt;</pre>
+
+                            <h2>${i18n.t('demo.consumer')}</h2>
+                            <p>${i18n.t('demo.consumer_description', {id: "c1", subscriptions: "border-color"})}</p>
+                            <pre>&lt;dbp-consumer  id="c1"  subscribe="border-color:bc" &gt;&lt;/dbp-consumer&gt;</pre>
+                            <dbp-consumer id="c1" subscribe="border-color:bc,lang:lang"></dbp-consumer>
+                            <p>${i18n.t('demo.consumer_description', {id: "c2", subscriptions: "foo"})}</p>
+                            <pre>&lt;dbp-consumer  id="c2"  subscribe="foo:foo" &gt;&lt;/dbp-consumer&gt;</pre>
+                            <dbp-consumer id="c2" subscribe="foo:foo,lang:lang"></dbp-consumer>
+                            <p>${i18n.t('demo.consumer_description', {id: "c3", subscriptions: "availability:status"})}</p>
+                            <p>Local <em>status</em> is provided as <em>availability</em></p>
+                            <pre>&lt;dbp-consumer  id="c3"  subscribe="status:availability"  border-color="orange" &gt;&lt;/dbp-consumer&gt;</pre>
+                            <dbp-consumer id="c3" subscribe="status:availability,lang:lang" border-color="orange"></dbp-consumer>
+                            <p>${i18n.t('demo.consumer_description', {id: "c4", subscriptions: "unknown-name:status"})}</p>
+                            <p>Remote <em>unknown-name</em> does not exist, the default value is overwritten by <em>undefined</em></i></p>
+                            <pre>&lt;dbp-consumer  id="c4"  subscribe="status:unknown-name"  border-color="darkgray" &gt;&lt;/dbp-consumer&gt;</pre>
+                            <dbp-consumer id="c4" subscribe="status:unknown-name" border-color="darkgray"></dbp-consumer>
+                        </div>
+                    </dbp-provider>
+                </dbp-provider>
             </section>
         `;
     }
@@ -120,163 +119,16 @@ commonUtils.defineCustomElement('dbp-provider-demo', ProviderDemo);
 
 // =======================================================
 
-class Consumer extends HTMLElement {
-    constructor() {
-        super();
-        this.connected = false;
-        this.deferInherited = false;
-        this.deferSubscribe = false;
-        this.deferUnSubscribe = false;
-
-        // default values
-        this.inherit = '';
-        this.subscribe = '';
-        this.unsubscribe = '';
-
-        this.attachShadow({mode: 'open'});
-        console.log('Consumer constructor()');
-    }
-
-    connectedCallback() {
-        console.log('Consumer(' + this.id() + ') connectedCallback()');
-
-        if (this.deferInherited) {
-            const attrs = this.inherit.split(',');
-            attrs.forEach(element => this.askProviderFor(element));
-            this.deferInherited = false;
-        }
-        if (this.deferUnSubscribe) {
-            const attrs = this.unsubscribe.split(',');
-            attrs.forEach(element => this.subscribeProviderFor(element));
-            this.deferSubscribe = false;
-            this.unsubscribe = '';
-        }
-        if (this.deferSubscribe) {
-            const attrs = this.subscribe.split(',');
-            attrs.forEach(element => this.subscribeProviderFor(element));
-            this.deferSubscribe = false;
-        }
-        this.connected = true;
-    }
-
-    static get observedAttributes() {
-        return ['inherit', 'subscribe'];
-    }
-
-    attributeChangedCallback(name, oldValue, newValue) {
-        console.log('Consumer(' + this.id() + ') attributeChangesCallback( ' + name + ', ' + oldValue + ', ' + newValue + ')');
-        switch(name) {
-            case 'inherit':
-                this.inherit = newValue;
-                if (this.connected && typeof newValue === 'string') {
-                    const attrs = newValue.split(',');
-                    attrs.forEach(element => this.askProviderFor(element));
-                } else {
-                    this.deferInherited = newValue.length > 0;
-                }
-                break;
-            case 'subscribe':
-                if (this.subscribe && this.subscribe.length > 0) {
-                    if (this.connected) {
-                        const attrs = this.subscribe.split(',');
-                        attrs.forEach(element => this.unSubscribeProviderFor(element));
-                    } else {
-                        this.deferUnSubscribe = this.subscribe.length > 0;
-                        this.unsubscribe = this.subscribe;
-                    }
-                }
-                if (newValue !== null) {
-                    this.subscribe = newValue;
-                    if (this.connected) {
-                        const attrs = newValue.split(',');
-                        attrs.forEach(element => this.subscribeProviderFor(element));
-                    } else {
-                        this.deferSubscribe = newValue && newValue.length > 0;
-                    }
-                }
-                break;
-            default:
-                console.log('unknown attribute "' + name + '".');
-        }
-    }
-
-    id() {
-        return this.getAttribute('id');
-    }
-
-    render() {}
-
-    askProviderFor(element) {
-        console.log('Consumer(' + this.id() + ') askProviderFor( ' + element + ' )');
-        const pair = element.trim().split(':');
-        const global = pair[0];
-        const local = pair[1];
-        const that = this;
-        const event = new CustomEvent('inherit',
-            {
-                bubbles: true,
-                composed: true,
-                detail: {
-                    name: global,
-                    callback: (value) => {
-                        console.log('Consumer(' + that.id() + ') ask/Callback ' + global + ' -> ' + local + ' = ' + value);
-                        this.attributeChangedCallback(local, that[local], value);
-                    }
-                }
-            });
-        this.parentElement.dispatchEvent(event);
-        //console.dir(event);
-    }
-
-    subscribeProviderFor(element) {
-        console.log('Consumer(' + this.id() + ') subscribeProviderFor( ' + element + ' )');
-        const pair = element.trim().split(':');
-        const global = pair[0];
-        const local = pair[1];
-        const that = this;
-        const event = new CustomEvent('subscribe',
-            {
-                bubbles: true,
-                composed: true,
-                detail: {
-                    name: global,
-                    callback: (value) => {
-                        console.log('Consumer(' + that.id() + ') sub/Callback ' + global + ' -> ' + local + ' = ' + value);
-                        this.attributeChangedCallback(local, that[local], value);
-                    },
-                    sender: this,
-                }
-            });
-        this.parentElement.dispatchEvent(event);
-    }
-
-    unSubscribeProviderFor(element) {
-        console.log('Consumer(' + this.id() + ') unSubscribeProviderFor( ' + element + ' )');
-        const pair = element.trim().split(':');
-        const global = pair[0];
-        const event = new CustomEvent('unsubscribe',
-            {
-                bubbles: true,
-                composed: true,
-                detail: {
-                    name: global,
-                    sender: this,
-                }
-            });
-        this.parentElement.dispatchEvent(event);
-    }
-}
-
-class DemoConsumer extends Consumer
-{
+class DemoConsumer extends DBPLitElement {
     constructor() {
         super();
 
+        this.lang = 'de';
         // default values
         this.foo = 100;
         this.bar = 900;
         this.ping = 0;
-        this['border-color'] = 'green';
+        this.borderColor = 'green';
 
         this.status = 'local';
 
@@ -285,17 +137,34 @@ class DemoConsumer extends Consumer
 
     connectedCallback() {
         super.connectedCallback();
-        console.log('DemoConsumer(' + this.id() + ') connectedCallback()');
+        i18n.changeLanguage(this.lang);
+        console.log('DemoConsumer(' + this.id + ') connectedCallback()');
         this.render();
     }
 
-    static get observedAttributes() {
-        return [ ...Consumer.observedAttributes, 'foo', 'bar', 'gong', 'border-color', 'ping'];
+    static get properties() {
+        return {
+            ...super.properties,
+            lang: { type: String },
+            foo: { type: String },
+            bar: { type: String },
+            gong: { type: String },
+            borderColor: { type: String, attribute: 'border-color' },
+            ping: { type: String }
+        };
     }
 
     attributeChangedCallback(name, oldValue, newValue) {
-        console.log('DemoConsumer(' + this.id() + ') attributeChangesCallback( ' + name + ', ' + oldValue + ', ' + newValue + ')');
+        if (oldValue === newValue) {
+            return;
+        }
+
+        console.log('DemoConsumer(' + this.id + ') attributeChangesCallback( ' + name + ', ' + oldValue + ', ' + newValue + ')');
         switch(name) {
+            case 'lang':
+                this.lang = newValue;
+                i18n.changeLanguage(this.lang);
+                break;
             case 'foo':
                 this.foo = parseInt(newValue);
                 break;
@@ -314,23 +183,27 @@ class DemoConsumer extends Consumer
         this.render();
     }
 
+    get id() {
+        return this.getAttribute('id');
+    }
+
     render() {
         if (! this.connected) {
-            return;
+            return `not connected!`;
         }
-        console.log('DemoConsumer(' + this.id() + ') render()');
+        console.log('DemoConsumer(' + this.id + ') render()');
 
         const sum = this.foo + this.bar;
-        this.shadowRoot.innerHTML = `
+        return html`
         <div style="border: ${this['border-color']} dotted; padding: 10px;">
             <table style="width:200px;">
                 <tr style="background-color: #aaa;">
-                    <th style="text-align: left;">Item</th>
-                    <th style="text-align: right;">Price</th>
+                    <th style="text-align: left;">${i18n.t('consumer.item')}</th>
+                    <th style="text-align: right;">${i18n.t('consumer.price')}</th>
                 </tr>
                 <tr><td>foo</td><td style="text-align: right;">${this.foo}</td></tr>
                 <tr><td>bar</td><td style="text-align: right;">${this.bar}</td></tr>
-                <tr><td>sum</td><td style="text-align: right;">${sum}</td></tr>
+                <tr><td>${i18n.t('consumer.sum')}</td><td style="text-align: right;">${sum}</td></tr>
             </table>
             <p>Status: <b>${this.status}</b></p>
         </div>
diff --git a/packages/provider/src/i18n/de/translation.json b/packages/provider/src/i18n/de/translation.json
index e41d874c7754dcb37b97245f41047f75b306965d..981c4287b852d1888e6e42792423d9799ae9fc83 100644
--- a/packages/provider/src/i18n/de/translation.json
+++ b/packages/provider/src/i18n/de/translation.json
@@ -1,5 +1,16 @@
 {
-  "provider": {
+  "de": "Deutsch",
+  "en": "Englisch",
 
+  "demo": {
+    "provider": "Anbieter",
+    "consumer": "Verbraucher",
+    "provider_description": "Anbieter \"{{id}}\" {{description}}",
+    "consumer_description": "Verbraucher \"{{id}}\" abonniert nur {{subscriptions}}"
+  },
+  "consumer": {
+    "item": "Bezeichnung",
+    "price": "Preis",
+    "sum": "Summe"
   }
 }
\ No newline at end of file
diff --git a/packages/provider/src/i18n/en/translation.json b/packages/provider/src/i18n/en/translation.json
index e41d874c7754dcb37b97245f41047f75b306965d..bc342774e83864c5cd6c4e4fda3c2f41c33847fa 100644
--- a/packages/provider/src/i18n/en/translation.json
+++ b/packages/provider/src/i18n/en/translation.json
@@ -1,5 +1,16 @@
 {
-  "provider": {
+  "de": "German",
+  "en": "English",
 
+  "demo": {
+    "provider": "Provider",
+    "consumer": "Consumer",
+    "provider_description": "Provider \"{{id}}\" {{description}}",
+    "consumer_description": "Consumer \"{{id}}\" will only subscribe to {{subscriptions}}"
+  },
+  "consumer": {
+    "item": "Description",
+    "price": "Price",
+    "sum": "sum"
   }
 }
\ No newline at end of file
diff --git a/packages/provider/src/provider.js b/packages/provider/src/provider.js
index 52eda0acba6e182345d72e58e04f5e528b16210f..7cd95fc0770c2f46184cb8613354d11efa73b430 100644
--- a/packages/provider/src/provider.js
+++ b/packages/provider/src/provider.js
@@ -2,59 +2,20 @@ export class Provider extends HTMLElement {
     constructor() {
         super();
         this.callbackStore = [];
+        this.root = false;
 
         console.log('Provider constructor()');
     }
 
-    static get observedAttributes() {
-        return ['init'];
-    }
-
-    attributeChangedCallback(name, oldValue, newValue) {
-        console.log('Provider(' + this.id() + ') attribute "' + name + '" changed from "' + oldValue + '" to "' + newValue + '".');
-        switch(name) {
-            case 'init':
-                this.init = newValue;
-                if (newValue) {
-                    const attrs = newValue.split(',');
-                    attrs.forEach(element => {
-                        const pair = element.trim().split('=');
-                        const name = pair[0].trim();
-                        const value = pair[1].trim().replace('"', '').replace("'", '');
-                        if (name.length > 0) {
-                            this[name] = value;
-                            this.callbackStore.forEach(item => {
-                                if (item.name === name) {
-                                    item.callback(value);
-                                }
-                            });
-                        }
-                    });
-                }
-                break;
-            default:
-                console.log('unknown attribute "' + name + '".');
-        }
-    }
-
-
     connectedCallback() {
-        console.log('Provider(' + this.id() + ') connectedCallback()');
+        console.log('Provider(' + this.id + ') connectedCallback()');
 
         const that = this;
-        this.addEventListener('inherit', function (e) {
-            if (that[e.detail.name]) {
-                console.log('Provider(' + that.id() + ') eventListener("inherit",..) name "' + e.detail.name + '" found.');
-                //console.dir(e.detail);
-                e.detail.callback(that[e.detail.name]);
-                e.stopPropagation();
-            }
-        }, false);
 
         this.addEventListener('subscribe', function (e) {
             const name = e.detail.name;
-            if (that[name]) {
-                console.log('Provider(' + that.id() + ') eventListener("subscribe",..) name "' + name + '" found.');
+            if (Object.hasOwnProperty.call(that, name) || that.root) {
+                console.log('Provider(' + that.id + ') eventListener("subscribe",..) name "' + name + '" found.');
                 that.callbackStore.push({name: name, callback: e.detail.callback, sender: e.detail.sender});
 
                 e.detail.callback(that[name]);
@@ -65,13 +26,13 @@ export class Provider extends HTMLElement {
         this.addEventListener('unsubscribe', function (e) {
             const name = e.detail.name;
             const sender = e.detail.sender;
-            if (that[name]) {
-                console.log('Provider(' + that.id() + ') eventListener("unsubscribe",..) name "' + name + '" found.');
+            if (Object.hasOwnProperty.call(that, name) || that.root) {
+                console.log('Provider(' + that.id + ') eventListener("unsubscribe",..) name "' + name + '" found.');
                 that.callbackStore.forEach(item => {
                     if (item.sender === sender && item.name === name) {
                         const index = that.callbackStore.indexOf(item);
                         that.callbackStore.splice(index, 1);
-                        console.log('Provider(' + that.id() + ') eventListener for name "' + name + '" removed.');
+                        console.log('Provider(' + that.id + ') eventListener for name "' + name + '" removed.');
                     }
                 });
 
@@ -84,8 +45,8 @@ export class Provider extends HTMLElement {
             const name = e.detail.name;
             const value = e.detail.value;
 
-            if (that[name]) {
-                console.log('Provider(' + that.id() + ') eventListener("set-property",..) name "' + name + '" found.');
+            if (Object.hasOwnProperty.call(that, name) || that.root) {
+                console.log('Provider(' + that.id + ') eventListener("set-property",..) name "' + name + '" found.');
                 that[name] = value;
 
                 that.callbackStore.forEach(item => {
@@ -97,9 +58,51 @@ export class Provider extends HTMLElement {
                 e.stopPropagation();
             }
         }, false);
+
+        // Options for the observer (which mutations to observe)
+        const config = { attributes: true, childList: false, subtree: false };
+
+        // Callback function to execute when mutations are observed
+        const callback = function(mutationsList, observer) {
+            // Use traditional 'for loops' for IE 11
+            for(const mutation of mutationsList) {
+                if (mutation.type === 'attributes') {
+                    const name = mutation.attributeName;
+                    const value = that.getAttribute(name);
+                    if (that[name] !== value) {
+                        console.log('Provider (' + that.id + ') observed attribute "' + name + '" changed');
+                        that[name] = value;
+                        that.callbackStore.forEach(item => {
+                            if (item.name === name) {
+                                item.callback(value);
+                            }
+                        });
+                    }
+                }
+            }
+        };
+
+        // Create an observer instance linked to the callback function
+        const observer = new MutationObserver(callback);
+
+        // Start observing the target node for configured mutations
+        observer.observe(this, config);
+
+        // get all *not observed* attributes
+        if (this.hasAttributes()) {
+            const attrs = this.attributes;
+            for(let i = attrs.length - 1; i >= 0; i--) {
+                if (['id', 'class', 'style', 'data-tag-name'].includes(attrs[i].name)) {
+                    continue;
+                }
+
+                this[attrs[i].name] = attrs[i].value;
+                console.log('Provider (' + that.id + ') found attribute "' + attrs[i].name + '" = "' + attrs[i].value + '"');
+            }
+        }
     }
 
-    id() {
+    get id() {
         return this.getAttribute('id');
     }
 }