protected override async Task OnParametersSetAsync() { await base.OnParametersSetAsync(); if (this.DefaultSelectedKeys != null) { foreach (var key in this.DefaultSelectedKeys) { AddSelection(key); } } if (this.DefaultSelectedOptions != null) { foreach (var option in this.DefaultSelectedOptions) { AddSelection(option.Key); } } if (ItemTemplate == null) { ItemTemplate = (item) => (builder) => { builder.OpenComponent <BFUDropdownItem>(0); builder.AddAttribute(1, "Text", item.Text); builder.AddAttribute(2, "Key", item.Key); builder.AddAttribute(3, "ItemType", item.ItemType); builder.AddAttribute(4, "Disabled", item.Disabled); builder.AddAttribute(5, "Hidden", item.Hidden); builder.CloseComponent(); }; } if (CascadedEditContext != null && (SelectedOptionExpression != null || SelectedOptionsExpression != null)) { if (SelectedOptionExpression != null) { FieldIdentifier = FieldIdentifier.Create <IBFUDropdownOption>(SelectedOptionExpression); } else { FieldIdentifier = FieldIdentifier.Create <IEnumerable <IBFUDropdownOption> >(SelectedOptionsExpression); } CascadedEditContext?.NotifyFieldChanged(FieldIdentifier); CascadedEditContext.OnValidationStateChanged += CascadedEditContext_OnValidationStateChanged; } }
public async Task ParsesCurrentValueAsStringWhenChanged_Valid() { // Arrange var model = new TestModel(); var valueChangedArgs = new List <DateTime>(); var rootComponent = new TestInputHostComponent <DateTime, TestDateInputComponent> { EditContext = new EditContext(model), ValueChanged = valueChangedArgs.Add, ValueExpression = () => model.DateProperty }; var fieldIdentifier = FieldIdentifier.Create(() => model.DateProperty); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent); var numValidationStateChanges = 0; rootComponent.EditContext.OnValidationStateChanged += (sender, eventArgs) => { numValidationStateChanges++; }; // Act await inputComponent.SetCurrentValueAsStringAsync("1991/11/20"); // Assert var receivedParsedValue = valueChangedArgs.Single(); Assert.Equal(1991, receivedParsedValue.Year); Assert.Equal(11, receivedParsedValue.Month); Assert.Equal(20, receivedParsedValue.Day); Assert.True(rootComponent.EditContext.IsModified(fieldIdentifier)); Assert.Empty(rootComponent.EditContext.GetValidationMessages(fieldIdentifier)); Assert.Equal(0, numValidationStateChanges); }
protected override void OnParametersSet() { if (CurrentEditContext == null) { throw new InvalidOperationException($"{GetType()} requires a cascading parameter " + $"of type {nameof(EditContext)}. For example, you can use {GetType()} inside " + $"an {nameof(EditForm)}."); } if (For == null) // Not possible except if you manually specify T { throw new InvalidOperationException($"{GetType()} requires a value for the " + $"{nameof(For)} parameter."); } if (For != _previousFieldAccessor) { _fieldIdentifier = FieldIdentifier.Create(For); _previousFieldAccessor = For; } if (CurrentEditContext != _previousEditContext) { DetachValidationStateChangedListener(); CurrentEditContext.OnValidationStateChanged += _validationStateChangedHandler; _previousEditContext = CurrentEditContext; } }
public async Task UnsubscribesFromValidationStateChangeNotifications() { // Arrange var model = new TestModel(); var rootComponent = new TestInputHostComponent <string, TestInputComponent <string> > { EditContext = new EditContext(model), ValueExpression = () => model.StringProperty }; var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty); var renderer = new TestRenderer(); var rootComponentId = renderer.AssignRootComponentId(rootComponent); await renderer.RenderRootComponentAsync(rootComponentId); var component = renderer.Batches.Single().GetComponentFrames <TestInputComponent <string> >().Single().Component; // Act: dispose, then update the field state in the EditContext and notify ((IDisposable)component).Dispose(); var messageStore = new ValidationMessageStore(rootComponent.EditContext); messageStore.Add(fieldIdentifier, "Some message"); await renderer.Dispatcher.InvokeAsync(rootComponent.EditContext.NotifyValidationStateChanged); // Assert: No additional render Assert.Empty(renderer.Batches.Skip(1)); }
protected override void OnInitialized() { if (CurrentEditContext is null) { throw new InvalidOperationException($"No Cascading Edit Context Found!"); } if (ValueExpression is null) { throw new InvalidOperationException($"No ValueExpression defined for the Control! Define a Bind-Value."); } if (!ValueChanged.HasDelegate) { throw new InvalidOperationException($"No ValueChanged defined for the Control! Define a Bind-Value."); } CurrentEditContext.OnFieldChanged += FieldChanged; _messageStore = new ValidationMessageStore(this.CurrentEditContext); if (_messageStore is null) { throw new InvalidOperationException($"Cannot set the Validation Message Store!"); } if (this.IsRequired && !string.IsNullOrWhiteSpace(this.HelperText)) { _fieldIdentifier = FieldIdentifier.Create(ValueExpression); if (!string.IsNullOrWhiteSpace(this.HelperText)) { _messageStore.Add(_fieldIdentifier, this.HelperText); } } }
public async Task UserSpecifiedAriaValueIsNotChangedIfInvalid() { // Arrange// Arrange var model = new TestModel(); var invalidContext = new EditContext(model); var rootComponent = new TestInputHostComponent <string, TestInputComponent <string> > { EditContext = invalidContext, ValueExpression = () => model.StringProperty }; rootComponent.AdditionalAttributes = new Dictionary <string, object>(); rootComponent.AdditionalAttributes["aria-invalid"] = "userSpecifiedValue"; var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty); var messageStore = new ValidationMessageStore(invalidContext); messageStore.Add(fieldIdentifier, "Test error message"); var renderer = new TestRenderer(); var rootComponentId = renderer.AssignRootComponentId(rootComponent); await renderer.RenderRootComponentAsync(rootComponentId); // Initally, it rendered one batch and is valid var batch1 = renderer.Batches.Single(); var componentFrame1 = batch1.GetComponentFrames <TestInputComponent <string> >().Single(); var inputComponentId = componentFrame1.ComponentId; var component = (TestInputComponent <string>)componentFrame1.Component; Assert.Equal("invalid", component.CssClass); Assert.NotNull(component.AdditionalAttributes); Assert.Equal(1, component.AdditionalAttributes.Count); Assert.Equal("userSpecifiedValue", component.AdditionalAttributes["aria-invalid"]); }
internal async Task InitializeInputExpression <T>(Expression <Func <T> > expression) { // Data-Annotation validation can only work if parent validationa and expression are defined. if ((ParentValidations != null || EditContext != null) && expression != null) { // We need to re-instantiate FieldIdentifier only if the model has changed. // Otherwise it could get pretty slow for larger forms. if (!hasFieldIdentifier || (ParentValidations?.Model?.IsEqual(fieldIdentifier.Model) == false) || (EditContext?.Model?.IsEqual(fieldIdentifier.Model) == false)) { fieldIdentifier = FieldIdentifier.Create(expression); // Re-run validation based on the new value for the new model, // but ONLY if validation has being previously initialized! if (hasFieldIdentifier && Mode == ValidationMode.Auto && ValidateOnLoad && initialized) { await NotifyInputChanged(expression.Compile().Invoke(), true); } hasFieldIdentifier = true; } } else { hasFieldIdentifier = false; } }
public void CannotCreateFromExpression_NonMember() { var ex = Assert.Throws <ArgumentException>(() => FieldIdentifier.Create(() => new TestModel())); Assert.Equal($"The provided expression contains a NewExpression which is not supported. {nameof(FieldIdentifier)} only supports simple member accessors (fields, properties) of an object.", ex.Message); }
public void CanCreateFromExpression_MemberOfConstantExpression() { var fieldIdentifier = FieldIdentifier.Create(() => StringPropertyOnThisClass); Assert.Same(this, fieldIdentifier.Model); Assert.Equal(nameof(StringPropertyOnThisClass), fieldIdentifier.FieldName); }
public async Task SuppliesFieldClassCorrespondingToFieldState() { // Arrange var model = new TestModel(); var rootComponent = new TestInputHostComponent <string, TestInputComponent <string> > { EditContext = new EditContext(model), ValueExpression = () => model.StringProperty }; var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty); // Act/Assert: Initially, it's valid and unmodified var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent); Assert.Equal("valid", inputComponent.CssClass); // no Class was specified // Act/Assert: Modify the field rootComponent.EditContext.NotifyFieldChanged(fieldIdentifier); Assert.Equal("modified valid", inputComponent.CssClass); // Act/Assert: Make it invalid var messages = new ValidationMessageStore(rootComponent.EditContext); messages.Add(fieldIdentifier, "I do not like this value"); Assert.Equal("modified invalid", inputComponent.CssClass); // Act/Assert: Clear the modification flag rootComponent.EditContext.MarkAsUnmodified(fieldIdentifier); Assert.Equal("invalid", inputComponent.CssClass); // Act/Assert: Make it valid messages.Clear(); Assert.Equal("valid", inputComponent.CssClass); }
public async Task ValidationErrorUsesDisplayAttributeName() { // Arrange var model = new TestModel(); var rootComponent = new TestInputHostComponent <int, TestInputNumberComponent> { EditContext = new EditContext(model), ValueExpression = () => model.SomeNumber, AdditionalAttributes = new Dictionary <string, object> { { "DisplayName", "Some number" } } }; var fieldIdentifier = FieldIdentifier.Create(() => model.SomeNumber); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent); // Act await inputComponent.SetCurrentValueAsStringAsync("notANumber"); // Assert var validationMessages = rootComponent.EditContext.GetValidationMessages(fieldIdentifier); Assert.NotEmpty(validationMessages); Assert.Contains("The Some number field must be a number.", validationMessages); }
protected override void OnInitialized() { if (!Checked.HasValue) { IsChecked = DefaultChecked; CheckedUncontrolled = true; } if (CascadedEditContext != null) { if (CheckedExpression == null) { throw new InvalidOperationException($"{GetType()} requires a value for the 'CheckedExpression' " + $"parameter. Normally this is provided automatically when using 'bind-Checked'."); } FieldIdentifier = FieldIdentifier.Create(CheckedExpression); if (ValidateOnInit) { CascadedEditContext.NotifyFieldChanged(FieldIdentifier); } CascadedEditContext.OnValidationStateChanged += CascadedEditContext_OnValidationStateChanged; } //IsChecked = Checked ?? DefaultChecked; //CheckedChanged.InvokeAsync(IsChecked); base.OnInitialized(); }
protected override void OnInitialized() { if (_editContext == null) { throw new InvalidOperationException($"{GetType()} requires a cascading parameter " + $"of type {nameof(Microsoft.AspNetCore.Components.Forms.EditContext)}. For example, you can use {GetType().FullName} inside " + $"an {nameof(EditForm)}."); } if (ValueExpression == null) { throw new InvalidOperationException($"{GetType()} requires a value for the 'ValueExpression' " + $"parameter. Normally this is provided automatically when using 'bind-Value'."); } _fieldIdentifier = FieldIdentifier.Create(ValueExpression); if (AdditionalAttributes is not null && AdditionalAttributes.TryGetValue("class", out var clsAttributeObj)) { _otherCssClasses = Convert.ToString(clsAttributeObj, CultureInfo.InvariantCulture) ?? string.Empty; } _simpleMode = Value is not null && Value.From.Count == 1 && Value.To.Count == 1 && Value.From[0] == Value.To[0]; _validationMessages = new ValidationMessageStore(_editContext); _editContext.OnValidationRequested += OnValidationRequested; _editContext.OnFieldChanged += CheckForChildFieldChanges; }
public async Task ValidationErrorUsesDisplayAttributeName() { // Arrange var model = new TestModel(); var rootComponent = new TestInputHostComponent <DateTime, TestInputDateComponent> { EditContext = new EditContext(model), ValueExpression = () => model.DateProperty, AdditionalAttributes = new Dictionary <string, object> { { "DisplayName", "Date property" } } }; var fieldIdentifier = FieldIdentifier.Create(() => model.DateProperty); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent); // Act await inputComponent.SetCurrentValueAsStringAsync("invalidDate"); // Assert var validationMessages = rootComponent.EditContext.GetValidationMessages(fieldIdentifier); Assert.NotEmpty(validationMessages); Assert.Contains("The Date property field must be a date.", validationMessages); }
protected override void OnParametersSet() { base.OnParametersSet(); _startIdentifier = FieldIdentifier.Create(StartExpression); _endIdentifier = FieldIdentifier.Create(EndExpression); }
protected override void OnParametersSet() { if (For != null) { _fieldIdentifier = FieldIdentifier.Create(For); } }
/// <summary> /// On parameters set method /// </summary> protected override void OnParametersSet() { // Check that the required parameters have been provided if (CurrentEditContext == null) { throw new InvalidOperationException( string.Format(Csla.Properties.Resources.CascadingEditContextRequiredException, nameof(CslaValidationMessages <string>), nameof(EditContext))); } if (For == null) { throw new ArgumentNullException("For"); } // Create a FieldIdentifier to use in recognising the field being validated _fieldIdentifier = FieldIdentifier.Create(For); // Wire up handling of the state change events we need event if (CurrentEditContext != _previousEditContext) { DetachPreviousEventHandlers(); CurrentEditContext.OnFieldChanged += _fieldChangedHandler; CurrentEditContext.OnValidationStateChanged += _validationStateChangedHandler; _previousEditContext = CurrentEditContext; } }
public async Task AriaAttributeIsRenderedWhenTheValidationStateIsInvalidOnFirstRender() { // Arrange// Arrange var model = new TestModel(); var invalidContext = new EditContext(model); var rootComponent = new TestInputHostComponent <string, TestInputComponent <string> > { EditContext = invalidContext, ValueExpression = () => model.StringProperty }; var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty); var messageStore = new ValidationMessageStore(invalidContext); messageStore.Add(fieldIdentifier, "Test error message"); var renderer = new TestRenderer(); var rootComponentId = renderer.AssignRootComponentId(rootComponent); await renderer.RenderRootComponentAsync(rootComponentId); // Initally, it rendered one batch and is valid var batch1 = renderer.Batches.Single(); var componentFrame1 = batch1.GetComponentFrames <TestInputComponent <string> >().Single(); var inputComponentId = componentFrame1.ComponentId; var component = (TestInputComponent <string>)componentFrame1.Component; Assert.Equal("invalid", component.CssClass); Assert.NotNull(component.AdditionalAttributes); Assert.Equal(1, component.AdditionalAttributes.Count); //Check for "true" see https://www.w3.org/TR/wai-aria-1.1/#aria-invalid Assert.Equal("true", component.AdditionalAttributes["aria-invalid"]); }
protected override void OnParametersSet() { if (For != null) { _fieldIdentifier = FieldIdentifier.Create(For); MyEditContext.OnValidationStateChanged += _validationStateChangedHandler; } }
public void CanCreateFromExpression_MemberOfObjectWithCast() { var model = new TestModel(); var fieldIdentifier = FieldIdentifier.Create(() => ((TestModel)(object)model).StringField); Assert.Same(model, fieldIdentifier.Model); Assert.Equal(nameof(TestModel.StringField), fieldIdentifier.FieldName); }
/// <summary> /// Обработка выбора файла в браузере /// </summary> /// <param name="eventArgs"></param> protected void OnChange(InputFileChangeEventArgs eventArgs) { //Получаем файл из браузера uploadViewModel.File = eventArgs.File; editContext.NotifyFieldChanged(FieldIdentifier.Create(() => uploadViewModel.File)); //Если тип файла совпадает с *.pdf показываем кнопку подтвердить isSubmit = Path.GetExtension(uploadViewModel.File.Name).Equals(".pdf"); }
public void CanCreateFromExpression_Field() { var model = new TestModel(); var fieldIdentifier = FieldIdentifier.Create(() => model.StringField); Assert.Same(model, fieldIdentifier.Model); Assert.Equal(nameof(model.StringField), fieldIdentifier.FieldName); }
/// <summary> /// 组件初始化方法 /// </summary> protected override void OnInitialized() { Columns?.Columns.Add(this); _fieldIdentifier = FieldIdentifier.Create(FieldExpression); if (Field != null) { FieldType = Field.GetType(); } }
protected override void OnInitialized() { base.OnInitialized(); if (FieldExpression != null) { _fieldIdentifier = FieldIdentifier.Create(FieldExpression); } }
protected override void OnInitialized() { if (FieldExpression != null) { _fieldIdentifier = FieldIdentifier.Create(FieldExpression); } Table?.AddColumn(this); }
public void CanCreateFromExpression_MemberOfChildObject() { var parentModel = new ParentModel { Child = new TestModel() }; var fieldIdentifier = FieldIdentifier.Create(() => parentModel.Child.StringField); Assert.Same(parentModel.Child, fieldIdentifier.Model); Assert.Equal(nameof(TestModel.StringField), fieldIdentifier.FieldName); }
internal void InitializeInputExpression <T>(Expression <Func <T> > expression) { if (expression == null) { return; } fieldIdentifier = FieldIdentifier.Create(expression); hasFieldIdentifier = true; }
private void OnValidationStateChangedCallback(object sender, EventArgs e) { if (ValidationMessageFor != null) { var fieldIdentifier = FieldIdentifier.Create(ValidationMessageFor); var validationMessage = string.Join("<br />", EditContext.GetValidationMessages(fieldIdentifier)); InvokeAsync(() => InvokeJsVoidAsync("MaterialBlazor.MBTextField.setHelperText", ElementReference, HelperTextReference, HelperText.Trim(), HelperTextPersistent, PerformsValidation, !string.IsNullOrEmpty(Value), validationMessage)); } }
public void CanCreateFromExpression_MemberOfIndexedCollectionEntry() { var models = new List <TestModel>() { null, new TestModel() }; var fieldIdentifier = FieldIdentifier.Create(() => models[1].StringField); Assert.Same(models[1], fieldIdentifier.Model); Assert.Equal(nameof(TestModel.StringField), fieldIdentifier.FieldName); }
public static void ValidateExpression <T>( EditContext editContext, Expression <Func <T> > expression) { if (expression == null || editContext == null) { return; } EditContext editContext1 = editContext; FieldIdentifier fieldIdentifier = FieldIdentifier.Create <T>(expression); ref FieldIdentifier local = ref fieldIdentifier;