Laravel Orchid自定义CodeMirror字段JS失效问题求助
Laravel Orchid自定义CodeMirror字段JS不生效的修复方案
问题描述
在Laravel Orchid中创建支持CodeMirror的自定义字段,完成JS控制器编写、Vite集成、Blade模板、PHP字段类等步骤后,字段仅显示原生textarea,CodeMirror未初始化生效。
核心问题与修复步骤
1. 控制器继承与Stimulus初始化规范问题
Orchid基于Stimulus框架,控制器需正确继承Stimulus的Controller类,且控制器别名需符合短横线命名规范,同时确保Stimulus实例正确初始化。
修改dashboard.js:
import { Application } from '@hotwired/stimulus'; import MirrorTextArea from "./controllers/mirrorTextArea.js"; // 初始化Stimulus应用 window.Stimulus = Application.start(); // 用短横线命名控制器别名,符合Stimulus规范 window.Stimulus.register("mirror-text-area", MirrorTextArea);
2. CodeMirror实例创建逻辑错误
- 不能将CodeMirror的父容器设为textarea本身,需隐藏原生textarea后在其位置插入编辑器
- 状态扩展配置错误,未正确添加行号、语言支持等功能
- 缺少编辑器内容与textarea的同步逻辑,导致表单提交无法获取值
修改JavaScript控制器:
import { EditorState } from '@codemirror/state'; import { EditorView, keymap, lineNumbers, highlightActiveLineGutter } from '@codemirror/view'; import { defaultKeymap } from '@codemirror/commands'; import { sql } from '@codemirror/lang-sql'; // MySQL模式需引入该依赖 export default class extends window.Stimulus.Controller { // 定义接收的属性值,自动处理类型转换 static values = { mode: String, lineNumbers: Boolean, theme: String }; connect() { const textarea = this.element.querySelector('textarea'); textarea.style.display = 'none'; // 隐藏原生textarea // 构建CodeMirror扩展数组 const extensions = [ keymap.of(defaultKeymap), ]; // 启用行号功能 if (this.lineNumbersValue) { extensions.push(lineNumbers(), highlightActiveLineGutter()); } // 添加SQL语言支持(根据模式调整) if (this.modeValue === 'text/x-mysql') { extensions.push(sql({ dialect: 'mysql' })); } // 创建编辑器状态 const state = EditorState.create({ doc: textarea.value, extensions: extensions }); // 在textarea的父容器中插入编辑器 const view = new EditorView({ state, parent: textarea.parentElement, }); // 同步编辑器内容到textarea,确保表单提交能获取值 view.dispatch({ effects: EditorView.updateListener.of((update) => { if (update.docChanged) { textarea.value = view.state.doc.toString(); } }) }); view.focus(); } }
3. Blade模板数据属性匹配问题
- 控制器别名需与Stimulus注册的别名一致
- 数据属性需使用
*-value后缀,对应控制器的static values定义 - textarea的name需使用字段的动态
$name属性,而非硬编码
修改Blade模板:
@component($typeForm, get_defined_vars()) <div data-controller="mirror-text-area" data-mirror-text-area-mode-value="{{ $mode }}" data-mirror-text-area-line-numbers-value="{{ $line_numbers ? 'true' : 'false' }}" data-mirror-text-area-theme-value="{{ $theme }}"> <textarea name="{{ $name }}" id="editor">{{ $value ?? '' }}</textarea> </div> @endcomponent
4. PHP字段类完善
- 添加工厂方法,支持链式设置字段属性
- 确保属性能正确传递到模板,修正字段类型为textarea
修改PHP字段类:
<?php namespace App\Orchid\Fields; use Orchid\Screen\Field; class MirrorTextArea extends Field { protected $view = 'fields.mirror-text-area'; protected string $type = 'textarea'; protected $attributes = [ 'mode' => "text/x-mysql", 'line_numbers' => true, 'theme' => "default", ]; // 链式设置方法 public function mode(string $mode): self { $this->set('mode', $mode); return $this; } public function lineNumbers(bool $status): self { $this->set('line_numbers', $status); return $this; } public function theme(string $theme): self { $this->set('theme', $theme); return $this; } }
5. 依赖与资源编译验证
- 安装缺失的依赖:
npm install @hotwired/stimulus @codemirror/state @codemirror/view @codemirror/commands @codemirror/lang-sql
- 编译前端资源:
npm run build
- 确保Orchid布局中已加载Vite资源(Orchid默认自动加载,可在
resources/views/vendor/orchid/layouts/dashboard.blade.php中确认)
验证使用
在Orchid屏幕中添加字段:
use App\Orchid\Fields\MirrorTextArea; public function query(): array { return [ 'query' => '', // 初始内容 ]; } public function layout(): iterable { return [ MirrorTextArea::make('query') ->mode('text/x-mysql') ->lineNumbers(true) ->theme('default'), ]; }
内容的提问来源于stack exchange,提问作者lan3er
相关产品推荐
相关产品推荐

