Maui icon indicating copy to clipboard operation
Maui copied to clipboard

[Bug] Email validation in iOS App shows text as red for valid email.

Open breezerc opened this issue 3 years ago • 5 comments

Description

I'm trying to use toolkit for email validation as it shown in microsoft documentation: <Entry> <Entry.Behaviors> <toolkit:EmailValidationBehavior InvalidStyle="{StaticResource InvalidEntryStyle}" ValidStyle="{StaticResource ValidEntryStyle}" Flags="ValidateOnValueChanged" /> </Entry.Behaviors> </Entry>

When I enter email like: [email protected] color is changed to green indicating valid email. For email like: [email protected] color stays red. image

And it works just fine in the Android emulator. So the problem on iOS only.

Expected Behavior

Text should be green for valid emails.

Actual Behavior

Text is red for valid email.

Basic Information

  • Version with issue: 1.2.0
  • Last known good version: n/a
  • IDE: VS 2022 17.3.0 release version.
  • Platform Target Frameworks:
    • iOS: Minimum iOS version is set to 14.2
    • Android: 21.0
  • Affected Devices: iPhone/iOS 15.6

Workaround

Reproduction imagery

iOS image Android Emulator: image

breezerc avatar Aug 14 '22 17:08 breezerc

Hi @breezerc! Could you add a small sample reproduction to help us reproduce the bug?

TheCodeTraveler avatar Aug 14 '22 17:08 TheCodeTraveler

I copy & pasted the code I mentioned from the Microsoft article. Here is the full xaml page:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             x:Class="MauiTestApp.MainPage">

    <ContentPage.Resources>
        <Style x:Key="InvalidEntryStyle" TargetType="Entry">
            <Setter Property="TextColor" Value="Red" />
        </Style>
        <Style x:Key="ValidEntryStyle" TargetType="Entry">
            <Setter Property="TextColor" Value="Green" />
        </Style>
    </ContentPage.Resources>
    
    <ScrollView>
        <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center">

            <Image
                Source="dotnet_bot.png"
                SemanticProperties.Description="Cute dot net bot waving hi to you!"
                HeightRequest="200"
                HorizontalOptions="Center" />

            <Label
                Text="Hello, World!"
                SemanticProperties.HeadingLevel="Level1"
                FontSize="32"
                HorizontalOptions="Center" />

            <Label
                Text="Welcome to .NET Multi-platform App UI"
                SemanticProperties.HeadingLevel="Level2"
                SemanticProperties.Description="Welcome to dot net Multi platform App U I"
                FontSize="18"
                HorizontalOptions="Center" />

            

            <Entry>
                <Entry.Behaviors>
                    <toolkit:EmailValidationBehavior 
                InvalidStyle="{StaticResource InvalidEntryStyle}"
                ValidStyle="{StaticResource ValidEntryStyle}"
                Flags="ValidateOnValueChanged" />
                </Entry.Behaviors>
            </Entry>

            <Button
                x:Name="CounterBtn"
                Text="Click me"
                SemanticProperties.Hint="Counts the number of times you click"
                Clicked="OnCounterClicked"
                HorizontalOptions="Center" />

        </VerticalStackLayout>
    </ScrollView>

</ContentPage>

The installed package:

	<ItemGroup>
	  <PackageReference Include="CommunityToolkit.Maui" Version="1.2.0" />
	</ItemGroup>

breezerc avatar Aug 14 '22 20:08 breezerc

Hm... I got the issue reproduced with this native code:

struct ContentView: View {
    @State private var email: String
    @State var emailIsValid: Bool = true
    
    public init(email: String = "")
    {
        self.email = email
    }
    
    var body: some View {
        Text("Hello, world!")
            .padding()
        
        TextField("Email", text: $email)
            .onChange(of: email) { newValue in
                if(newValue.range(of:"^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$", options: .regularExpression) != nil) {
                    self.emailIsValid = true
                    print("valid")
                } else {
                    self.emailIsValid = false
                    print("invalid")
                }
            }
            .foregroundColor(emailIsValid ? Color.green : Color.red)
    }
}

While I see "valid" printed in the console. The text color stays red.

Test cases: [email protected] - text is green [email protected] - text is red.

Tested both on real iPhone and on emulator.

breezerc avatar Aug 14 '22 21:08 breezerc

@breezerc would be great if you could upload your sample project here. You just need to zip the project past and drag and drop it here, or upload the sample to GitHub and share the link. Even if we copy and paste the code here we can configure our project with another pattern and not reproduce the issue and waste time.

pictos avatar Aug 14 '22 21:08 pictos

I found the problem. By default keyboard uses 'Default' type which on iOS includes Spell checking. The spell checking making the text red in the failed test cases. The fix is either disable spell checking:

<Entry.Keyboard>
                    <Keyboard x:FactoryMethod="Create">
                        <x:Arguments>
                            <KeyboardFlags>None</KeyboardFlags>
                        </x:Arguments>
                    </Keyboard>
                </Entry.Keyboard>

Or set the keyboard for the entry to the 'Email' type:

 <Entry
                x:Name="EmailEntry"
                HorizontalOptions="Fill"
                FontSize="Medium"
                Keyboard="Email"
                >

It would be good to update the Microsoft documentation here: Microsoft Article

breezerc avatar Aug 14 '22 22:08 breezerc

Incredible detective work, @breezerc!! This makes sense why I couldn't reproduce the bug by passing [email protected] into our Unit Tests.

I wonder if it makes sense for EmailValidationBehavior to set InputView.Keyboard = Keyboard.Email? We could add this code to EmailValidationBehavior.cs:

protected override void OnAttachedTo(VisualElement bindable)
{
  if(bindable is InputView inputView)
  {
    inputView.Keyboard = Keyboard.Email;
  }

  base.OnAttachedTo(bindable);
}

TheCodeTraveler avatar Aug 15 '22 18:08 TheCodeTraveler

Thanks!

If you want my opinion I'm split here. From one side it makes total sense. From another side it is a validation behavior changing keyboard layout. May be seen as unexpected side effect. Probably change the documentation + comment on this may be a slightly better.

breezerc avatar Aug 16 '22 19:08 breezerc