diff --git a/source/components/datatable/dataset.mjs b/source/components/datatable/dataset.mjs
index 36a28f1e1b2220755733ad031e7d9170c91ce583..8ba57d28944f87291d5fea44ffb5473cfd48a631 100644
--- a/source/components/datatable/dataset.mjs
+++ b/source/components/datatable/dataset.mjs
@@ -12,33 +12,33 @@
  * SPDX-License-Identifier: AGPL-3.0
  */
 
-import { instanceSymbol, internalSymbol } from "../../constants.mjs";
-import { Pathfinder } from "../../data/pathfinder.mjs";
-import { getLinkedObjects, hasObjectLink } from "../../dom/attributes.mjs";
-import { customElementUpdaterLinkSymbol } from "../../dom/constants.mjs";
+import {instanceSymbol, internalSymbol} from "../../constants.mjs";
+import {Pathfinder} from "../../data/pathfinder.mjs";
+import {getLinkedObjects, hasObjectLink} from "../../dom/attributes.mjs";
+import {customElementUpdaterLinkSymbol} from "../../dom/constants.mjs";
 import {
-	assembleMethodSymbol,
-	CustomElement,
-	attributeObserverSymbol,
-	registerCustomElement,
+    assembleMethodSymbol,
+    CustomElement,
+    attributeObserverSymbol,
+    registerCustomElement,
 } from "../../dom/customelement.mjs";
-import { findElementWithSelectorUpwards } from "../../dom/util.mjs";
-import { isString } from "../../types/is.mjs";
-import { Observer } from "../../types/observer.mjs";
-import { clone } from "../../util/clone.mjs";
+import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
+import {isString} from "../../types/is.mjs";
+import {Observer} from "../../types/observer.mjs";
+import {clone} from "../../util/clone.mjs";
 import {
-	ATTRIBUTE_DATASOURCE_SELECTOR,
-	ATTRIBUTE_DATATABLE_INDEX,
+    ATTRIBUTE_DATASOURCE_SELECTOR,
+    ATTRIBUTE_DATATABLE_INDEX,
 } from "./constants.mjs";
-import { Datasource } from "./datasource.mjs";
-import { DatasetStyleSheet } from "./stylesheet/dataset.mjs";
+import {Datasource} from "./datasource.mjs";
+import {DatasetStyleSheet} from "./stylesheet/dataset.mjs";
 import {
-	handleDataSourceChanges,
-	datasourceLinkedElementSymbol,
+    handleDataSourceChanges,
+    datasourceLinkedElementSymbol,
 } from "./util.mjs";
-import { FormStyleSheet } from "../stylesheet/form.mjs";
+import {FormStyleSheet} from "../stylesheet/form.mjs";
 
-export { DataSet };
+export {DataSet};
 
 /**
  * The data set component is used to show the data of a data source.
@@ -79,184 +79,219 @@ export { DataSet };
  * @summary A data set
  */
 class DataSet extends CustomElement {
-	/**
-	 * This method is called by the `instanceof` operator.
-	 * @returns {symbol}
-	 */
-	static get [instanceSymbol]() {
-		return Symbol.for("@schukai/monster/components/dataset@@instance");
-	}
-
-	/**
-	 * This method determines which attributes are to be monitored by `attributeChangedCallback()`.
-	 *
-	 * @return {string[]}
-	 * @since 1.15.0
-	 */
-	static get observedAttributes() {
-		const attributes = super.observedAttributes;
-		attributes.push(ATTRIBUTE_DATATABLE_INDEX);
-		return attributes;
-	}
-
-	/**
-	 * To set the options via the html tag the attribute `data-monster-options` must be used.
-	 * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
-	 *
-	 * The individual configuration values can be found in the table.
-	 *
-	 * @property {Object} templates Template definitions
-	 * @property {string} templates.main Main template
-	 * @property {object} datasource The datasource
-	 * @property {string} datasource.selector The selector of the datasource
-	 * @property {object} mapping The mapping
-	 * @property {string} mapping.data The data
-	 * @property {number} mapping.index The index
-	 * @property {Array} data The data
-	 */
-	get defaults() {
-		const obj = Object.assign({}, super.defaults, {
-			templates: {
-				main: getTemplate(),
-			},
-
-			datasource: {
-				selector: null,
-			},
-
-			mapping: {
-				data: "dataset",
-				index: 0,
-			},
-
-			data: {},
-		});
-
-		updateOptionsFromArguments.call(this, obj);
-		return obj;
-	}
-
-	/**
-	 *
-	 * @return {string}
-	 */
-	static getTag() {
-		return "monster-dataset";
-	}
-
-	write() {
-		return new Promise((resolve, reject) => {
-			if (!this[datasourceLinkedElementSymbol]) {
-				reject(new Error("No datasource"));
-				return;
-			}
-
-			const internalUpdateCloneData = this.getInternalUpdateCloneData();
-			if (!internalUpdateCloneData) {
-				reject(new Error("No update data"));
-				return;
-			}
-
-			const internalData = internalUpdateCloneData?.["data"];
-			if (
-				internalData === undefined ||
-				internalData === null ||
-				internalData === ""
-			) {
-				reject(new Error("No data"));
-				return;
-			}
-
-			setTimeout(() => {
-				const path = this.getOption("mapping.data");
-				const index = this.getOption("mapping.index");
-
-				let pathWithIndex;
-
-				if (isString(path) && path !== "") {
-					pathWithIndex = path + "." + index;
-				} else {
-					pathWithIndex = index;
-				}
-
-				const data = this[datasourceLinkedElementSymbol].data;
-				const unref = JSON.stringify(data);
-				const ref = JSON.parse(unref);
-
-				new Pathfinder(ref).setVia(pathWithIndex, internalData);
-
-				this[datasourceLinkedElementSymbol].data = ref;
-
-				resolve();
-			}, 0);
-		});
-	}
-
-	/**
-	 * This method is responsible for assembling the component.
-	 *
-	 * It calls the parent's assemble method first, then initializes control references and event handlers.
-	 * If the `datasource.selector` option is provided and is a string, it searches for the corresponding
-	 * element in the DOM using that selector.
-	 *
-	 * If the selector matches exactly one element, it checks if the element is an instance of the `Datasource` class.
-	 *
-	 * If it is, the component's `datasourceLinkedElementSymbol` property is set to the element, and the component
-	 * attaches an observer to the datasource's changes.
-	 *
-	 * The observer is a function that calls the `handleDataSourceChanges` method in the context of the component.
-	 * Additionally, the component attaches an observer to itself, which also calls the `handleDataSourceChanges`
-	 * method in the component's context.
-	 */
-	[assembleMethodSymbol]() {
-		super[assembleMethodSymbol]();
-
-		// initControlReferences.call(self);
-		initEventHandler.call(this);
-
-		const selector = this.getOption("datasource.selector");
-
-		if (isString(selector)) {
-			const element = findElementWithSelectorUpwards(this, selector);
-			if (element === null) {
-				throw new Error("the selector must match exactly one element");
-			}
-
-			if (!(element instanceof Datasource)) {
-				throw new TypeError("the element must be a datasource");
-			}
-
-			this[datasourceLinkedElementSymbol] = element;
-			element.datasource.attachObserver(
-				new Observer(handleDataSourceChanges.bind(this)),
-			);
-		}
-
-		this.attachObserver(
-			new Observer(() => {
-				handleDataSourceChanges.call(this);
-			}),
-		);
-	}
-
-	/**
-	 * @return [CSSStyleSheet]
-	 */
-	static getCSSStyleSheet() {
-		return [FormStyleSheet, DatasetStyleSheet];
-	}
+    /**
+     * This method is called by the `instanceof` operator.
+     * @returns {symbol}
+     */
+    static get [instanceSymbol]() {
+        return Symbol.for("@schukai/monster/components/dataset@@instance");
+    }
+
+    /**
+     * This method determines which attributes are to be monitored by `attributeChangedCallback()`.
+     *
+     * @return {string[]}
+     * @since 1.15.0
+     */
+    static get observedAttributes() {
+        const attributes = super.observedAttributes;
+        attributes.push(ATTRIBUTE_DATATABLE_INDEX);
+        return attributes;
+    }
+
+    /**
+     * To set the options via the html tag the attribute `data-monster-options` must be used.
+     * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
+     *
+     * The individual configuration values can be found in the table.
+     *
+     * @property {Object} templates Template definitions
+     * @property {string} templates.main Main template
+     * @property {object} datasource The datasource
+     * @property {string} datasource.selector The selector of the datasource
+     * @property {object} mapping The mapping
+     * @property {string} mapping.data The data
+     * @property {number} mapping.index The index
+     * @property {Array} data The data
+     */
+    get defaults() {
+        const obj = Object.assign({}, super.defaults, {
+            templates: {
+                main: getTemplate(),
+            },
+
+            datasource: {
+                selector: null,
+            },
+
+            mapping: {
+                data: "dataset",
+                index: 0,
+            },
+
+            features: {
+                /**
+                 * @since 3.70.0
+                 * @type {boolean}
+                 */
+                refreshOnMutation: true,
+            },
+
+            /**
+             * @since 3.70.0
+             * @type {boolean}
+             */
+            refreshOnMutation: {
+                selector: "input, select, textarea"
+            },
+
+            data: {},
+        });
+
+        updateOptionsFromArguments.call(this, obj);
+        return obj;
+    }
+
+    /**
+     *
+     * @return {string}
+     */
+    static getTag() {
+        return "monster-dataset";
+    }
+
+    /**
+     * This method is called when the component is created.
+     * @since 3.70.0
+     * @returns {DataSet}
+     */
+    refresh() {
+        // makes sure that handleDataSourceChanges is called
+        this.setOption("data", {});
+        return this;
+    }
+
+    /**
+     *
+     * @returns {Promise<unknown>}
+     */
+    write() {
+        return new Promise((resolve, reject) => {
+            if (!this[datasourceLinkedElementSymbol]) {
+                reject(new Error("No datasource"));
+                return;
+            }
+
+            const internalUpdateCloneData = this.getInternalUpdateCloneData();
+            if (!internalUpdateCloneData) {
+                reject(new Error("No update data"));
+                return;
+            }
+
+            const internalData = internalUpdateCloneData?.["data"];
+            if (
+                internalData === undefined ||
+                internalData === null ||
+                internalData === ""
+            ) {
+                reject(new Error("No data"));
+                return;
+            }
+
+            setTimeout(() => {
+                const path = this.getOption("mapping.data");
+                const index = this.getOption("mapping.index");
+
+                let pathWithIndex;
+
+                if (isString(path) && path !== "") {
+                    pathWithIndex = path + "." + index;
+                } else {
+                    pathWithIndex = String(index);
+                }
+
+                const data = this[datasourceLinkedElementSymbol].data;
+                const unref = JSON.stringify(data);
+                const ref = JSON.parse(unref);
+
+                new Pathfinder(ref).setVia(pathWithIndex, internalData);
+
+                this[datasourceLinkedElementSymbol].data = ref;
+
+                resolve();
+            }, 0);
+        });
+    }
+
+    /**
+     * This method is responsible for assembling the component.
+     *
+     * It calls the parent's assemble method first, then initializes control references and event handlers.
+     * If the `datasource.selector` option is provided and is a string, it searches for the corresponding
+     * element in the DOM using that selector.
+     *
+     * If the selector matches exactly one element, it checks if the element is an instance of the `Datasource` class.
+     *
+     * If it is, the component's `datasourceLinkedElementSymbol` property is set to the element, and the component
+     * attaches an observer to the datasource's changes.
+     *
+     * The observer is a function that calls the `handleDataSourceChanges` method in the context of the component.
+     * Additionally, the component attaches an observer to itself, which also calls the `handleDataSourceChanges`
+     * method in the component's context.
+     */
+    [assembleMethodSymbol]() {
+        super[assembleMethodSymbol]();
+
+        initEventHandler.call(this);
+
+        const selector = this.getOption("datasource.selector");
+
+        if (isString(selector)) {
+            const element = findElementWithSelectorUpwards(this, selector);
+            if (element === null) {
+                throw new Error("the selector must match exactly one element");
+            }
+
+            if (!(element instanceof Datasource)) {
+                throw new TypeError("the element must be a datasource");
+            }
+
+            this[datasourceLinkedElementSymbol] = element;
+            element.datasource.attachObserver(
+                new Observer(handleDataSourceChanges.bind(this)),
+            );
+        }
+
+        this.attachObserver(
+            new Observer(() => {
+                handleDataSourceChanges.call(this);
+            }),
+        );
+        
+        if (this.getOption("features.refreshOnMutation")&&this.getOption("refreshOnMutation.selector")) {
+            initMutationObserver.call(this);
+        }
+		
+    }
+
+    /**
+     * @return [CSSStyleSheet]
+     */
+    static getCSSStyleSheet() {
+        return [FormStyleSheet, DatasetStyleSheet];
+    }
 }
 
 /**
  * @private
  */
 function initEventHandler() {
-	this[attributeObserverSymbol][ATTRIBUTE_DATATABLE_INDEX] = () => {
-		const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
-		if (index) {
-			this.setOption("mapping.index", parseInt(index, 10));
-		}
-	};
+    this[attributeObserverSymbol][ATTRIBUTE_DATATABLE_INDEX] = () => {
+        const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
+        if (index) {
+            this.setOption("mapping.index", parseInt(index, 10));
+        }
+    };
 }
 
 /**
@@ -264,26 +299,67 @@ function initEventHandler() {
  * @param {Object} options
  */
 function updateOptionsFromArguments(options) {
-	const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
+    const index = this.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
 
-	if (index !== null && index !== undefined) {
-		options.mapping.index = parseInt(index, 10);
-	}
+    if (index !== null && index !== undefined) {
+        options.mapping.index = parseInt(index, 10);
+    }
 
-	const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
+    const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
 
-	if (selector) {
-		options.datasource.selector = selector;
-	}
+    if (selector) {
+        options.datasource.selector = selector;
+    }
 }
 
+/**
+ * @private
+ */
+function initMutationObserver() {
+
+    const config = {attributes: false, childList: true, subtree: true};
+
+    const callback = (mutationList, observer) => {
+
+        if (mutationList.length === 0) {
+            return;
+        }
+
+        let doneFlag = false;
+        for (const mutation of mutationList) {
+
+            if (mutation.type === "childList") {
+                for (const node of mutation.addedNodes) {
+                    if(node instanceof HTMLElement && node.matches(this.getOption("refreshOnMutation.selector"))) {
+                        doneFlag = true;
+                        break;
+                    }
+                }
+                
+                if (doneFlag) {
+                    break;
+                }
+            }
+        }
+
+        if (doneFlag) {
+            this.refresh();
+        }
+    };
+
+    const observer = new MutationObserver(callback);
+    observer.observe(this, config);
+
+}
+
+
 /**
  * @private
  * @return {string}
  */
 function getTemplate() {
-	// language=HTML
-	return `
+    // language=HTML
+    return `
         <div data-monster-role="control" part="control">
             <slot></slot>
         </div>