B4J Tutorial [ABMaterial]: Creating a Sign In Modal Dialog with Options: Part 2.1

Hi there

Part 2.1 seeks to address the UX design for the "Try Something Else" screen. This occurs when a user has forgotten the password but then instead of having it sent they just change it.


Goal

1. The user selects Forgot Password from the Sign In Screen
2. They are provided with an option to have the email sent to them or
3. Have an option to Try Something else, thus entering their registered email address and a new password.
4. The email, password and confirm password are compulsory.
5. The entered email address should exist in the database
6. The password and confirm password should match
7. The minimum password length should be about 8 characters, used a character counter as a guide.

As you have noted from part 1,2 and 3 of this tutorial, we are almost doing the same thing, reading data from a database, validating and verifying some information and writing stuff back to the database, so the route is still the same.

Reproduction

Let's create the Change Password modal sheet.

B4X:
Private Sub contLoginBuild() As ABMModalSheet
    Dim contLogin As ABMModalSheet
    Dim dSize As Int = ABM.MODALSHEET_SIZE_NORMAL
    If ABMShared.IsPhone(page) Then dSize = ABM.MODALSHEET_SIZE_FULL
    contLogin.Initialize(page, "contLogin", False, ABM.MODALSHEET_TYPE_NORMAL, "ms")
    contLogin.Size = dSize
    contLogin.IsDismissible = False
    contLogin.IsTextSelectable = True
    contLogin.Content.AddRows(1,True,"").AddCells12(1, "")
    contLogin.Content.AddRows(1,True,"").AddCellsOSMPV(1, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, ABM.VISIBILITY_ALL, "")
    contLogin.Content.AddRows(1,True,"").AddCellsOSMPV(1, 0, 0, 0, 12, 12, 12, 0, 0, 10, 0, ABM.VISIBILITY_ALL, "")
    contLogin.Content.AddRows(1,True,"").AddCellsOSMPV(1, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, ABM.VISIBILITY_ALL, "")
    contLogin.Content.AddRows(1,True,"").AddCellsOSMPV(1, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, ABM.VISIBILITY_ALL, "")
    contLogin.Content.AddRows(1,True,"").AddCellsOSMPV(1, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, ABM.VISIBILITY_ALL, "")
    contLogin.Content.AddRows(1,True,"").AddCellsOSMPV(1, 0, 0, 0, 12, 12, 12, 0, 0, 10, 10, ABM.VISIBILITY_ALL, "")
    contLogin.Header.BuildGrid  'IMPORTANT once you loaded the complete grid AND before you start adding components
    contLogin.Content.BuildGrid 'IMPORTANT once you loaded the complete grid AND before you start adding components
    contLogin.Footer.BuildGrid  'IMPORTANT once you loaded the complete grid AND before you start adding components
    'Add components to ModalSheet
    Dim imglogo As ABMImage
    imglogo.Initialize(page, "imglogo", "../images/logo.png?"& DateTime.Now, 1)
    imglogo.Tag = "imglogo"
    imglogo.IsResponsive = False
    imglogo.IsCircular = False
    imglogo.IsClickable = False
    imglogo.IsMaterialBoxed = False
    contLogin.Content.Cell(2,1).AddComponent(imglogo)
    Dim lblheader As ABMLabel
    lblheader.Initialize(page, "lblheader", $"{B}Change password{/B}"$, ABM.SIZE_PARAGRAPH, False, "")
    lblheader.istextselectable = True
    lblheader.supportemoji = False
    contLogin.Content.Cell(3,1).AddComponent(lblheader)
    Dim lblsubheader As ABMLabel
    lblsubheader.Initialize(page, "lblsubheader", $"Create a new, strong password that you don't use anywhere else"$, ABM.SIZE_PARAGRAPH, False, "")
    lblsubheader.istextselectable = True
    lblsubheader.supportemoji = False
    contLogin.Content.Cell(3,1).AddComponent(lblsubheader)
    Dim txtemail As ABMInput
    txtemail.Initialize(page, "txtemail", ABM.INPUT_EMAIL, "Email Address", False, "")
    txtemail.Tag = "txtemail"
    contLogin.Content.Cell(4,1).AddComponent(txtemail)
    Dim txtpassword As ABMInput
    txtpassword.Initialize(page, "txtpassword", ABM.INPUT_PASSWORD, "Password", False, "")
    txtpassword.Tag = "txtpassword"
    contLogin.Content.Cell(5,1).AddComponent(txtpassword)
    Dim txtconfirmpassword As ABMInput
    txtconfirmpassword.Initialize(page, "txtconfirmpassword", ABM.INPUT_PASSWORD, "Confirm Password", False, "")
    txtconfirmpassword.Tag = "txtconfirmpassword"
    contLogin.Content.Cell(6,1).AddComponent(txtconfirmpassword)
    Dim btnChangePassword As ABMButton
    btnChangePassword.InitializeRaised(page, "btnChangePassword", "", "", "Change Password", "")
    btnChangePassword.Tag = "btnChangePassword"
    btnChangePassword.UseFullCellWidth = True
    btnChangePassword.Size = ABM.BUTTONSIZE_NORMAL
    btnChangePassword.dropdownhidearrow = False
    btnChangePassword.dropdownshowbelow = False
    btnChangePassword.dropdownconstrainwidth = False
    contLogin.Content.Cell(7,1).AddComponent(btnChangePassword)
    Return contLogin
End Sub

Then we need to read the entered content, validate and verify it and then write the new password back to the database.

B4X:
Sub contLoginGetContents() As Map
    Dim pMap As Map
    pMap.Initialize
    Dim contLogin As ABMModalSheet
    contLogin = page.ModalSheet("contLogin")
    Dim txtemail As ABMInput = contLogin.Content.Component("txtemail")
    Dim txtpassword As ABMInput = contLogin.Content.Component("txtpassword")
    Dim txtconfirmpassword As ABMInput = contLogin.Content.Component("txtconfirmpassword")
    pMap.put("email", txtemail.Text)
    pMap.put("password", txtpassword.Text)
    pMap.put("confirmpassword", txtconfirmpassword.Text)
    Return pMap
End Sub
'Get the contents of the modal sheet from GetContents and check validity
Sub contLoginValidate(gMap As Map) As Boolean
    Dim contLogin As ABMModalSheet
    contLogin = page.ModalSheet("contLogin")
    Dim stxtemail As String
    stxtemail = gMap.get("email")
    If stxtemail = "null" Then stxtemail = ""
    If stxtemail.Length = 0 Then
        ABMShared.Warn(page,"Email Address cannot be blank. Please enter a value.")
        Dim txtemail As ABMInput = contLogin.Content.Component("txtemail")
        txtemail.SetFocus
        Return False
    End If
    Dim stxtpassword As String
    stxtpassword = gMap.get("password")
    If stxtpassword = "null" Then stxtpassword = ""
    If stxtpassword.Length = 0 Then
        ABMShared.Warn(page,"Password cannot be blank. Please enter a value.")
        Dim txtpassword As ABMInput = contLogin.Content.Component("txtpassword")
        txtpassword.SetFocus
        Return False
    End If
    Dim stxtconfirmpassword As String
    stxtconfirmpassword = gMap.get("confirmpassword")
    If stxtconfirmpassword = "null" Then stxtconfirmpassword = ""
    If stxtconfirmpassword.Length = 0 Then
        ABMShared.Warn(page,"Confirm Password cannot be blank. Please enter a value.")
        Dim txtconfirmpassword As ABMInput = contLogin.Content.Component("txtconfirmpassword")
        txtconfirmpassword.SetFocus
        Return False
    End If
    Return True
End Sub

The actual method that does all the magic..

B4X:
Private Sub contLoginChangePassword() As Boolean
    'define a map to hold the form contents
    Dim m As Map
    'read the form contents to a map
    m = contLoginGetContents
    'validate the form contents where required
    If contLoginValidate(m) = False Then
        Return False
    End If
    m.remove("id")
    Dim email As String = m.getdefault("email","")
    Dim password As String = m.getdefault("password","")
    Dim confirmpassword As String = m.getdefault("confirmpassword","")
    'the form contents are ok, continue with the change password process
    'define the search criteria, fields must equal
    Dim w As Map
    Dim UserMap As Map
    w.Initialize
    Dim nk As String
    nk = "email="
    w.put(nk, email)
    'Get connection from current pool if MySQL/MSSQL
    Dim jSQL As SQL = ABMShared.SQLGet
    Dim UserMap As Map = ABMShared.SQLSelectRecordWhereMap(jSQL,"users", w)
    If UserMap.IsInitialized = False Then
        ABMShared.Warn(page,"The Email specified could not be found in our records, please specify the correct email.")
        Return False
    End If
    If password <> confirmpassword Then
        ABMShared.Warn(page,"The passwords DO NOT match, please correct this!")
        Return False
    End If
    'The email has been found, update the passwords
    UserMap.put("email",email)
    UserMap.put("password",password)
    UserMap.put("confirmpassword",confirmpassword)
    Dim bUpdate As Boolean = ABMShared.SQLRecordUpdate(jSQL, "users", UserMap, "email", email)
    If bUpdate = True Then
        myToastId = myToastId + 1
        page.ShowToast("toast" & myToastId, "toastgreen", "Password updated successfully.", 3000,False)
        'Close the connection to the database
        ABMShared.SQLClose(jSQL)
        Return True
    Else
        myToastId = myToastId + 1
        page.ShowToast("toast" & myToastId, "toastred", "Password could NOT be updated successfully.", 3000,False)
        'Close the connection to the database
        ABMShared.SQLClose(jSQL)
        Return False
    End If
End Sub

Things to remember...

1. The modal sheet is now built on ConnectPage and not on BuildPage

B4X:
Public Sub ConnectPage()
    'connect navigation bar
    ConnectNavigationBar
    'add components for the page
    AdminAccess
    page.SetFontStack("arial,sans-serif")
    ' this page uses uploads, so needs some settings
    page.ws.session.SetAttribute("abmcallback", Me)
    page.ws.session.SetAttribute("abmdownloadfolder", DownloadFolder)
    page.ws.session.SetAttribute("abmmaxsize", DownloadMaxSize)
    page.AddModalSheetTemplate(contLoginBuild)
    page.Refresh ' IMPORTANT
    ' NEW, because we use ShowLoaderType=ABM.LOADER_TYPE_MANUAL
    page.FinishedLoading 'IMPORTANT
    page.RestoreNavigationBarPosition
    page.ShowModalSheet("contLogin")
End Sub
 

Attachments

  • frmChangePassword.bas
    20 KB · Views: 418
Top