예제 #1
0
        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;
            }
        }
예제 #2
0
    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);
    }
예제 #3
0
        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;
            }
        }
예제 #4
0
    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));
    }
예제 #5
0
        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);
                }
            }
        }
예제 #6
0
    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"]);
    }
예제 #7
0
        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;
            }
        }
예제 #8
0
    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);
    }
예제 #9
0
    public void CanCreateFromExpression_MemberOfConstantExpression()
    {
        var fieldIdentifier = FieldIdentifier.Create(() => StringPropertyOnThisClass);

        Assert.Same(this, fieldIdentifier.Model);
        Assert.Equal(nameof(StringPropertyOnThisClass), fieldIdentifier.FieldName);
    }
예제 #10
0
    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);
    }
예제 #11
0
    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);
    }
예제 #12
0
        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;
        }
예제 #14
0
    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);
    }
예제 #15
0
        protected override void OnParametersSet()
        {
            base.OnParametersSet();

            _startIdentifier = FieldIdentifier.Create(StartExpression);
            _endIdentifier   = FieldIdentifier.Create(EndExpression);
        }
예제 #16
0
 protected override void OnParametersSet()
 {
     if (For != null)
     {
         _fieldIdentifier = FieldIdentifier.Create(For);
     }
 }
예제 #17
0
        /// <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;
            }
        }
예제 #18
0
    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"]);
    }
예제 #19
0
 protected override void OnParametersSet()
 {
     if (For != null)
     {
         _fieldIdentifier = FieldIdentifier.Create(For);
         MyEditContext.OnValidationStateChanged += _validationStateChangedHandler;
     }
 }
예제 #20
0
    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");
 }
예제 #22
0
    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);
    }
예제 #23
0
 /// <summary>
 /// 组件初始化方法
 /// </summary>
 protected override void OnInitialized()
 {
     Columns?.Columns.Add(this);
     _fieldIdentifier = FieldIdentifier.Create(FieldExpression);
     if (Field != null)
     {
         FieldType = Field.GetType();
     }
 }
예제 #24
0
        protected override void OnInitialized()
        {
            base.OnInitialized();

            if (FieldExpression != null)
            {
                _fieldIdentifier = FieldIdentifier.Create(FieldExpression);
            }
        }
예제 #25
0
        protected override void OnInitialized()
        {
            if (FieldExpression != null)
            {
                _fieldIdentifier = FieldIdentifier.Create(FieldExpression);
            }

            Table?.AddColumn(this);
        }
예제 #26
0
    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);
    }
예제 #27
0
        internal void InitializeInputExpression <T>(Expression <Func <T> > expression)
        {
            if (expression == null)
            {
                return;
            }

            fieldIdentifier    = FieldIdentifier.Create(expression);
            hasFieldIdentifier = true;
        }
예제 #28
0
        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));
            }
        }
예제 #29
0
    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);
    }
예제 #30
0
 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;