Elementor多重复器组件内联编辑无法保存的问题求助
问题还原
我做了一个Elementor自定义Widget,里面加了两个Repeater组件,每个Repeater里都有一个文本控件,想支持内联编辑。现在单个Repeater的时候,内联编辑和保存都正常,但加了第二个Repeater后,内联编辑能正常触发,但修改后的内容就是保存不了。我用的是add_inline_editing_attributes方法来实现内联编辑,请问这种多Repeater的场景下,要怎么处理才能让内联编辑的内容正常保存?
问题代码
protected function register_controls() { $this->start_controls_section( 'content_section', [ 'label' => esc_html__( 'Test Plugin', 'test-plugin-td' ), 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ] ); $repeater = new Repeater(); $repeater->add_control( 'text', [ 'label' => __( 'Business Hour', 'test-plugin-td' ), 'type' => \Elementor\Controls_Manager::TEXT, 'label_block' => true, 'placeholder' => __( 'First Name', 'test-plugin-td' ), 'default' => __( 'First Name', 'test-plugin-td' ), 'dynamic' => [ 'active' => true, ], ] ); $this->add_control( 'business_hours', [ 'label' => __( 'Test Plugin', 'test-plugin-td' ), 'type' => \Elementor\Controls_Manager::REPEATER, 'fields' => $repeater->get_controls(), 'default' => [ [ 'text' => __( 'First Name', 'test-plugin-td' ), ], [ 'text' => __( 'Last Name', 'test-plugin-td' ), ], ], 'title_field' => '{{{ text }}}', ] ); $this->end_controls_section(); $this->start_controls_section( 'content_2section', [ 'label' => esc_html__( 'Test Plugin', 'test-plugin-td' ), 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ] ); $repeskeater = new Repeater(); $repeskeater->add_control( 'text2', [ 'label' => __( 'Business Hour', 'test-plugin-td' ), 'type' => \Elementor\Controls_Manager::TEXT, 'label_block' => true, 'placeholder' => __( 'First Name', 'test-plugin-td' ), 'default' => __( 'First Name', 'test-plugin-td' ), 'dynamic' => [ 'active' => true, ], ] ); $this->add_control( 'business_2hours', [ 'label' => __( 'Test Plugin', 'test-plugin-td' ), 'type' => \Elementor\Controls_Manager::REPEATER, 'fields' => $repeskeater->get_controls(), 'default' => [ [ 'text' => __( 'First Name', 'test-plugin-td' ), ], [ 'text' => __( 'Last Name', 'test-plugin-td' ), ], ], 'title_field' => '{{{ text2 }}}', ] ); $this->end_controls_section(); } protected function render() { $settings = $this->get_settings_for_display(); echo '<ul class="test-plugin-td">'; foreach ( $settings['business_hours'] as $index => $item ) : $text_key = $this->get_repeater_setting_key( 'text', 'business_hours', $index ); $this->add_inline_editing_attributes( $text_key ); ?> <li class="business-hour-item"> <span <?php $this->print_render_attribute_string( $text_key ); ?>> <?php echo esc_html( $item['text'] ); ?> </span> </li> <?php endforeach; echo '</ul>'; echo '<ul class="test-plugin-td">'; foreach ( $settings['business_2hours'] as $index => $item ) : $text_key = $this->get_repeater_setting_key( 'text2', 'business_2hours', $index ); $this->add_inline_editing_attributes( $text_key ); ?> <li class="business-hour-item"> <span <?php $this->print_render_attribute_string( $text_key ); ?>> <?php echo esc_html( $item['text2'] ); ?> </span> </li> <?php endforeach; echo '</ul>'; }
解决方案&问题分析
我之前做Elementor Widget的时候也碰到过一模一样的问题,核心原因有两个,给你一步步解决:
1. 第二个Repeater的默认值key写错了(致命错误)
看你第二个Repeater的default配置里,用的是'text'作为key,但你第二个Repeater的文本控件key是text2啊!这个错误会导致Elementor无法正确映射默认值到控件,进而影响内联编辑的保存逻辑——因为Elementor找不到对应的控件绑定,修改后的数据就存不进去。
赶紧把第二个Repeater的default改成:
'default' => [ [ 'text2' => __( 'First Name', 'test-plugin-td' ), ], [ 'text2' => __( 'Last Name', 'test-plugin-td' ), ], ],
2. 内联编辑属性要明确指定控件类型
虽然Elementor的add_inline_editing_attributes方法第二个参数是可选的,但在多Repeater场景下,必须明确指定控件类型(比如'basic'对应文本控件),这样Elementor才能准确识别不同Repeater里的控件,避免冲突。
修改render方法里的两行add_inline_editing_attributes代码:
- 第一个Repeater的:
$this->add_inline_editing_attributes( $text_key, 'basic' );
- 第二个Repeater的:
$this->add_inline_editing_attributes( $text_key, 'basic' );
3. 额外检查:确保Repeater实例完全独立
你这里已经新建了两个不同的Repeater实例($repeater和$repeskeater),这部分是对的,千万不要复用同一个Repeater实例来创建多个Repeater控件,否则一定会出现数据绑定冲突。
修正后的完整代码
protected function register_controls() { $this->start_controls_section( 'content_section', [ 'label' => esc_html__( 'Test Plugin', 'test-plugin-td' ), 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ] ); $repeater = new Repeater(); $repeater->add_control( 'text', [ 'label' => __( 'Business Hour', 'test-plugin-td' ), 'type' => \Elementor\Controls_Manager::TEXT, 'label_block' => true, 'placeholder' => __( 'First Name', 'test-plugin-td' ), 'default' => __( 'First Name', 'test-plugin-td' ), 'dynamic' => [ 'active' => true, ], ] ); $this->add_control( 'business_hours', [ 'label' => __( 'Test Plugin', 'test-plugin-td' ), 'type' => \Elementor\Controls_Manager::REPEATER, 'fields' => $repeater->get_controls(), 'default' => [ [ 'text' => __( 'First Name', 'test-plugin-td' ), ], [ 'text' => __( 'Last Name', 'test-plugin-td' ), ], ], 'title_field' => '{{{ text }}}', ] ); $this->end_controls_section(); $this->start_controls_section( 'content_2section', [ 'label' => esc_html__( 'Test Plugin', 'test-plugin-td' ), 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ] ); $repeskeater = new Repeater(); $repeskeater->add_control( 'text2', [ 'label' => __( 'Business Hour', 'test-plugin-td' ), 'type' => \Elementor\Controls_Manager::TEXT, 'label_block' => true, 'placeholder' => __( 'First Name', 'test-plugin-td' ), 'default' => __( 'First Name', 'test-plugin-td' ), 'dynamic' => [ 'active' => true, ], ] ); $this->add_control( 'business_2hours', [ 'label' => __( 'Test Plugin', 'test-plugin-td' ), 'type' => \Elementor\Controls_Manager::REPEATER, 'fields' => $repeskeater->get_controls(), // 修正默认值的key为text2 'default' => [ [ 'text2' => __( 'First Name', 'test-plugin-td' ), ], [ 'text2' => __( 'Last Name', 'test-plugin-td' ), ], ], 'title_field' => '{{{ text2 }}}', ] ); $this->end_controls_section(); } protected function render() { $settings = $this->get_settings_for_display(); echo '<ul class="test-plugin-td">'; foreach ( $settings['business_hours'] as $index => $item ) : $text_key = $this->get_repeater_setting_key( 'text', 'business_hours', $index ); // 明确指定控件类型为basic $this->add_inline_editing_attributes( $text_key, 'basic' ); ?> <li class="business-hour-item"> <span <?php $this->print_render_attribute_string( $text_key ); ?>> <?php echo esc_html( $item['text'] ); ?> </span> </li> <?php endforeach; echo '</ul>'; echo '<ul class="test-plugin-td">'; foreach ( $settings['business_2hours'] as $index => $item ) : $text_key = $this->get_repeater_setting_key( 'text2', 'business_2hours', $index ); // 明确指定控件类型为basic $this->add_inline_editing_attributes( $text_key, 'basic' ); ?> <li class="business-hour-item"> <span <?php $this->print_render_attribute_string( $text_key ); ?>> <?php echo esc_html( $item['text2'] ); ?> </span> </li> <?php endforeach; echo '</ul>'; }
做完这两个修改后,你再测试一下,两个Repeater的内联编辑应该都能正常保存了。
备注:内容来源于stack exchange,提问作者FERDAUSSK 01

