Replies: 3 comments 1 reply
-
So, I've realized that perhaps my entry point in my webpack.config.js may have been wrong, as it was pointing towards codemirror_editor.js and not the actual packages in node_modules (like it is done in the bundled node integration example). As well, I've tried modifying my codemirror_editor.js to not do GET http://127.0.0.1:8080/dist/merge.js net::ERR_ABORTED 404 (Not Found) I believe this is happening because inside my codemirror_editor.js file, they cannot find my merge.js. I can't seem to understand why. I've also gone simpler and only npm installed @codemirror/merge . So, basically, if i do static imports, i get the relative path issue, but if i do await imports, i get the above issue. Thus, my files are the following: this is my same directory: this is my package.json {
"scripts": {
"build": "webpack --config webpack.config.js"
},
"dependencies": {
"@codemirror/merge": "^6.0.1"
},
"devDependencies": {
"@babel/core": "^7.24.5",
"@babel/preset-env": "^7.24.5",
"babel-loader": "^9.1.3",
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4"
}
} this is my codemirror_editor.js let mergeViewInstance;
export default async function createCodeMirrorEditor(element, props) {
const initialValueA = props.value_a || "";
const initialValueB = props.value_b || "";
// Dynamically import CodeMirror modules
const { MergeView } = await import("/dist/merge.js");
const { EditorView } = await import("/dist/view.js");
const { EditorState } = await import("/dist/state.js");
mergeViewInstance = new MergeView({
a: {
doc: initialValueA,
extensions: [
EditorView.editable.of(true),
// Removed other extensions for simplicity - you can add them back if needed
EditorView.updateListener.of((update) => {
if (update.docChanged) {
sendUpdate('a', update.state.doc.toString());
}
}),
],
},
b: {
doc: initialValueB,
extensions: [
EditorView.editable.of(true),
// Removed other extensions for simplicity - you can add them back if needed
EditorView.updateListener.of((update) => {
if (update.docChanged) {
sendUpdate('b', update.state.doc.toString());
}
}),
],
},
parent: element,
root: document,
});
function sendUpdate(side, value) {
element.dispatchEvent(new CustomEvent('update-value', { detail: { side, value } }));
}
function setValue(side, value) {
const editor = side === 'a' ? mergeViewInstance.a : mergeViewInstance.b;
const transaction = editor.state.update({
changes: { from: 0, to: editor.state.doc.length, insert: value }
});
editor.dispatch(transaction);
}
return {
setValue: setValue,
destroy: () => { mergeViewInstance.destroy(); }
};
} this is my codemirror_editor.py from nicegui import ui
from typing import Callable, Optional
class CodeMirrorEditor(ui.element, component='codemirror_editor.js', dependencies=[
'dist/merge.js',
'dist/view.js',
'dist/state.js',
]):
def __init__(self,
value_a: str = "",
value_b: str = "",
on_change_a: Optional[Callable] = None,
on_change_b: Optional[Callable] = None
) -> None:
super().__init__()
self._props['value_a'] = value_a
self._props['value_b'] = value_b
self.on_change_a = on_change_a
self.on_change_b = on_change_b
self.on('update-value', self.handle_change)
def handle_change(self, event):
side = event.args['detail']['side']
value = event.args['detail']['value']
if side == 'a':
self._props['value_a'] = value
if self.on_change_a:
self.on_change_a(value)
elif side == 'b':
self._props['value_b'] = value
if self.on_change_b:
self.on_change_b(value)
self.update()
def set_value(self, side: str, value: str):
if side not in ('a', 'b'):
raise ValueError("side must be 'a' or 'b'")
self.run_method('setValue', side, value)
@property
def value_a(self) -> str:
return self._props['value_a']
@value_a.setter
def value_a(self, value: str) -> None:
self._props['value_a'] = value
self.set_value('a', value)
self.update()
@property
def value_b(self) -> str:
return self._props['value_b']
@value_b.setter
def value_b(self, value: str) -> None:
self.props['value_b'] = value
self.set_value('b', value)
self.update() this is my webpack.config.js const path = require("path");
module.exports = {
entry: {
merge: "@codemirror/merge",
view: "@codemirror/view",
state: "@codemirror/state",
},
mode: "development",
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].js",
library: "CodeMirrorMerge",
libraryTarget: "umd",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
},
],
},
}; |
Beta Was this translation helpful? Give feedback.
-
Hello again, I just wanted to update where I am, I think I've progressed, but the same kind of filepath error is occuring, just with a different console output. I've decided to add back all my desired dependencies, and re-added my webpack entry as codemirror_editor.js since that is where I want the bundle to start. However, now this is my console output:
I've also noticed that inside my codemirror_editor.py, only the value of my component is being uploaded onto the network. Such, I can only see codemirrorbundle.js when However, if i were to change it to This is how my directory looks like: this is my package.json: {
"scripts": {
"build": "webpack --config webpack.config.js"
},
"dependencies": {
"@codemirror/commands": "^6.4.0",
"@codemirror/lang-markdown": "^6.2.4",
"@codemirror/merge": "^6.0.1",
"@codemirror/state": "^6.4.1",
"@codemirror/view": "^6.25.4",
"codemirror": "^6.0.1"
},
"devDependencies": {
"@babel/core": "^7.24.5",
"@babel/preset-env": "^7.24.5",
"babel-loader": "^9.1.3",
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4"
}
} this is my webpack.config.js: const path = require("path");
module.exports = {
entry: "./codemirror_editor.js",
mode: "development",
output: {
path: path.resolve(__dirname, "dist"),
filename: "codemirrorbundle.js",
library: "CodeMirrorMerge",
libraryTarget: "umd",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
},
],
},
}; this is my codemirror_editor.js: let mergeViewInstance;
export default async function createCodeMirrorEditor(element, props) {
const initialValueA = props.value_a || "";
const initialValueB = props.value_b || "";
// Dynamically import CodeMirror modules
const { MergeView } = await import("@codemirror/merge");
const { EditorView } = await import("@codemirror/view");
const { basicSetup } = await import("codemirror");
const { EditorState } = await import("@codemirror/state");
const { markdown } = await import("@codemirror/lang-markdown");
const { keymap, defaultKeymap } = await import("@codemirror/view");
const { defaultKeymap: commandsDefaultKeymap } = await import("@codemirror/commands");
mergeViewInstance = new MergeView({
a: {
doc: initialValueA,
extensions: [
basicSetup,
markdown(),
EditorView.editable.of(true),
keymap.of(defaultKeymap),
EditorView.updateListener.of((update) => {
if (update.docChanged) {
sendUpdate('a', update.state.doc.toString());
}
}),
],
},
b: {
doc: initialValueB,
extensions: [
basicSetup,
markdown(),
EditorView.editable.of(true),
keymap.of(defaultKeymap),
EditorView.updateListener.of((update) => {
if (update.docChanged) {
sendUpdate('b', update.state.doc.toString());
}
}),
],
},
parent: element,
root: document,
});
function sendUpdate(side, value) {
element.dispatchEvent(new CustomEvent('update-value', { detail: { side, value } }));
}
function setValue(side, value) {
const editor = side === 'a' ? mergeViewInstance.a : mergeViewInstance.b;
const transaction = editor.state.update({
changes: { from: 0, to: editor.state.doc.length, insert: value }
});
editor.dispatch(transaction);
}
return {
setValue: setValue,
destroy: () => { mergeViewInstance.destroy(); }
};
} this is my codemirror_editor.py: from nicegui import ui
from typing import Callable, Optional
class CodeMirrorEditor(ui.element, component='dist/codemirrorbundle.js', dependencies=['dist/codemirrorbundle.js']):
def __init__(self,
value_a: str = "",
value_b: str = "",
on_change_a: Optional[Callable] = None,
on_change_b: Optional[Callable] = None
) -> None:
super().__init__()
self._props['value_a'] = value_a
self._props['value_b'] = value_b
self.on_change_a = on_change_a
self.on_change_b = on_change_b
self.on('update-value', self.handle_change)
def handle_change(self, event):
side = event.args['side']
value = event.args['value']
if side == 'a':
self._props['value_a'] = value
if self.on_change_a:
self.on_change_a(value)
elif side == 'b':
self._props['value_b'] = value
if self.on_change_b:
self.on_change_b(value)
self.update()
def set_value(self, side: str, value: str):
if side not in ('a', 'b'):
raise ValueError("side must be 'a' or 'b'")
self.run_method('setValue', side, value)
@property
def value_a(self) -> str:
return self._props['value_a']
@value_a.setter
def value_a(self, value: str) -> None:
self._props['value_a'] = value
self.set_value('a', value)
self.update()
@property
def value_b(self) -> str:
return self._props['value_b']
@value_b.setter
def value_b(self, value: str) -> None:
self._props['value_b'] = value
self.set_value('b', value)
self.update() this is my main.py: from nicegui import ui
from codemirror_editor import CodeMirrorEditor
@ui.page('/')
async def page():
editor = CodeMirrorEditor(value_a="# Initial A", value_b="Initial B")
ui.run() |
Beta Was this translation helpful? Give feedback.
-
Hi @ayejays, I'm sorry to hear that you have so much trouble integrating a third-party library into NiceGUI. I hoped it would be easier nowadays. |
Beta Was this translation helpful? Give feedback.
-
Hello,
I am part of a team of softwares developers (part of a company of around ~50 people) looking forward to launch a dashboard using the NiceGUI framework. However, I've run into a small issue. Currently, I'm trying to integrate CodeMirror 6 (including the
merge
addon andlang-markdown
) into my NiceGUI application, following the node module integration example in the documentation link. However, the page fails to render, and I consistently get the following error in the browser's developer console:Uncaught TypeError: Failed to resolve module specifier "codemirror". Relative references must start with either "/", "./", or "../".
I've tried simplifying my code to a minimal example, but the error persists. I suspect there might be an issue with how I'm handling the webpack bundle.
Currently, I am on NICEGUI v2.0.0, python 3.12.7, node v22.13.1, and npm v11.0.0
This is how my directory looks like:
nicegui-codemirror-minimal/
├── dist/
│ └── codemirror-bundle.js
├── node_modules/
│ └── ...
├── codemirror_editor.js
├── codemirror_editor.py
├── main.py
├── package.json
├── package-lock.json
└── webpack.config.js
this is my package.json:
this is my webpack.config.js:
this is my codemirror_editor.json:
this is my codemirror_editor.py:
this is my main.py:
This is what my browser looks like:

Beta Was this translation helpful? Give feedback.
All reactions