我确实想要创建一个不包含任何输入的自定义控件。每当控件改变时,我都想保存完整的表单。
我们当前的方法使用像这样的形式更改事件:
library(shiny)
library(ggplot2)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
uiOutput("Cylselectui"),
submitButton("Apply changes")
),
mainPanel(
plotOutput("Carsplot")
)
)
)
server <- function(input, output) {
output$Carsplot <- renderPlot({
plotdata <- subset(mtcars, cyl %in% input$Cylselection) #Filter based on cyl
ggplot(plotdata, aes(x = mpg, y = hp, colour = factor(cyl))) + #Create plot
geom_point()
})
output$Cylselectui <- renderUI({ #Create the cyl selectize ui based on the values of cyl that are in the data
selectizeInput(
'Cylselection', 'Select by Cylinder',
choices = sort(unique(mtcars$cyl)),
selected = sort(unique(mtcars$cyl)),
multiple = TRUE
)
})
}
shinyApp(ui = ui, server = server)
正如您所看到的,我们使用&#34;更改&#34; -event来对表单中的任何更改做出反应。 只要我们有输入,复选框,......作为控件,这样就可以正常工作。
但是我们的自定义控件只存在于我们可以单击的简单div中。每当我点击div时,控件的值都会增加1.但是不会触发表单的&#34;更改&#34; -event。我是否必须以某种方式将我的自定义控件链接到表单?或者是否有任何需要解雇的事件?
<form #demoForm="ngForm" (change)="onChange()">
<custom-input name="someValue" [(ngModel)]="dataModel">
</custom-input>
</form>
我已经创建了一个用于演示问题的plunker: https://plnkr.co/edit/ushMfJfcmIlfP2U1EW6A
每当您点击&#34;点击&#34;模型值增加,但控制台上没有输出,因为更改事件未被触发...(有一个与更改事件链接的console.log)
答案 0 :(得分:5)
感谢您的回复。
最后我找到了以下解决这个问题的方法: 正如评论中提到的Claies一样,我的自定义组件不会触发更改事件。因此,表格永远不会知道这种变化。这与angular没什么关系,但正如所说的是输入/表单的预期行为。
最简单的解决方案是在发生更改时触发customcontrol中的change-event:
constructor(private element: ElementRef, private renderer: Renderer) {
}
public triggerChanged(){
let event = new CustomEvent('change', {bubbles: true});
this.renderer.invokeElementMethod(this.element.nativeElement, 'dispatchEvent', [event]);
}
只要我打电话给#34; onControlChange(..)&#34;那就是它。在我的自定义组件中,然后我随后触发此事件。
请注意,您需要Custom-Event-Polyfill来支持IE! https://www.npmjs.com/package/custom-event-polyfill
答案 1 :(得分:1)
感谢Stefan向我指出正确的方向。
不幸的是,不赞成使用Renderer(具有invokeElementMethod()
)或赞成Renderer2(不具有该方法)
所以以下内容对我有用
this.elementRef.nativeElement.dispatchEvent(new CustomEvent('change', { bubbles: true }));
答案 2 :(得分:0)
您需要将div的click事件发送到其父级。这样你就可以处理这个事件了。
父组件:
import { Component, forwardRef, Output, EventEmitter } from '@angular/core'; // add output and eventEmitter
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
@Component({
selector: 'custom-input',
template: `<div (click)="update($event)">Click</div>`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true
}]
})
export class CustomInputComponent implements ControlValueAccessor {
private onTouchedCallback: () => void = () => {};
private onChangeCallback: (_: any) => void = () => {};
@Output() clickEvent = new EventEmitter(); // add this
update(event){
this.value++;
this.clickEvent.emit(event); // emit the event on click event
}
get value(): any {
return this.innerValue;
};
}
子组件:
//our root app component
import {Component} from '@angular/core'
@Component({
selector: 'demo-app',
template: `
<p><span class="boldspan">Model data:</span> {{dataModel}}</p>
<form #demoForm="ngForm">
<custom-input name="someValue"
[(ngModel)]="dataModel" (clickEvent) = onChange()> // handling emitted event here
Write in this wrapper control:
</custom-input>
</form>`
})
export class AppComponent {
dataModel: string = '';
public onChange(){
console.log("onChangeCalled");
}
}
答案 3 :(得分:0)
当您调用change
onChange回调(在ControlValueAccessor
函数中传递的回调)时,似乎没有在表单上触发registerOnChange
事件,但总体上可以观察到valueChanges
形式)。
代替:
...
<form (change)="onChange()">
...
您可以尝试使用:
this.form.valueChanges
.subscribe((formValues) => {
...
});
当然,您必须在组件中获得正确的表格参考。