Hello,
I'm trying to use a dynamic field to allow users to add more text inputs for email addresses. Currently, the email address fields all show whatever the most recent text added is--only showing the same email address in all of the boxes.
What am I doing wrong? Thank you for any help.
{ a!columnsLayout( columns: a!columnLayout( contents: { a!richTextDisplayField( labelPosition: "COLLAPSED", value: { a!richTextItem( text: "Notification Recipients", style: "STRONG" ) } ), a!forEach( items: local!emailNotify, expression: { a!sideBySideLayout( items: { a!sideBySideItem( item: a!textField( label: "Email Address" & " " & fv!index, labelPosition: "COLLAPSED", placeholder: "group@google.com", value: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{3ceaa747-1816-40cd-af23-175364e4a157}distribution_list'], saveInto: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{3ceaa747-1816-40cd-af23-175364e4a157}distribution_list'], refreshAfter: "UNFOCUS", characterLimit: 255, validations: { a!validationMessage( message: "An email is required.", validateAfter: "UNFOCUS", showWhen: a!isNullOrEmpty(local!emailNotify) ) } ) ), a!sideBySideItem( item: a!richTextDisplayField( labelPosition: "COLLAPSED", value: { a!richTextIcon( icon: "times", altText: "Remove email address", link: a!dynamicLink( saveInto: a!save( local!emailNotify, remove(local!emailNotify, fv!index) ) ), linkStyle: "STANDALONE" ) }, showWhen: count(local!emailNotify) > 1 ), width: "MINIMIZE" ) }, alignVertical: "MIDDLE" ) } ), a!richTextDisplayField( labelPosition: "COLLAPSED", value: a!richTextItem( text: { a!richTextIcon(icon: "plus", altText: "plus"), " ", "Add Email Address" }, link: a!dynamicLink( saveInto: { a!save( local!emailNotify, append(local!emailNotify, " ") ) } ), linkStyle: "STANDALONE" ), accessibilityText: "Clicking this link will add another email address input above." ) }, width: "NARROW_PLUS" ) ) },
Discussion posts and replies are publicly visible
On the surface, it looks like there is a loop of text fields `a!forEach(local!emailNotify,...)` , but each text field in the loop references the same ri!record in its saveInto.
I might need some more context to give a better answer though. What's the definition of `local!emailNotify` ? Is ri!record a single record or an array?
This might be interesting: https://appian.rocks/2023/12/04/the-master-of-email-address-fields/
You're correct, I'm not sure of a setup that would allow me to collect the emails. This is the full code. I have the local variable at the top. ri!record is a single record.
a!localVariables( local!emailNotify: { "" }, a!formLayout( label: "Create Maintenance Notification", contents: { a!columnsLayout( columns: { a!columnLayout( contents: { a!textField( label: "Description", labelPosition: "ABOVE", instructions: "This is also the subject of any notification emails", placeholder: "The description of the maintenance ", value: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{18c5ba82-03ee-4b8f-a415-b769ca5b5472}description'], saveInto: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{18c5ba82-03ee-4b8f-a415-b769ca5b5472}description'], characterLimit: 400, required: true ) } ) } ), a!columnsLayout( columns: { a!columnLayout( contents: { a!paragraphField( label: "Details", labelPosition: "ABOVE", placeholder: "The details of the maintenance ", value: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{4bb71bf3-b82d-46a1-bc01-5cdf3b4bc041}details'], saveInto: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{4bb71bf3-b82d-46a1-bc01-5cdf3b4bc041}details'], refreshAfter: "UNFOCUS", characterLimit: 4000, height: "MEDIUM", required: true, validations: {} ), a!dateTimeField( label: "Maintenance Window Start", labelPosition: "ABOVE", value: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{ca1765a7-b49a-417a-8f69-79710c56d8c5}maintenance_window_start'], saveInto: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{ca1765a7-b49a-417a-8f69-79710c56d8c5}maintenance_window_start'], required: true ), a!dateTimeField( label: "Maintenance Window End", labelPosition: "ABOVE", value: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{be98a17d-f7ec-4980-a5f6-84d775ba522f}maintenance_window_end'], saveInto: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{be98a17d-f7ec-4980-a5f6-84d775ba522f}maintenance_window_end'], required: true, validations: { if( and( a!isNotNullOrEmpty( ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{be98a17d-f7ec-4980-a5f6-84d775ba522f}maintenance_window_end'] ), a!isNotNullOrEmpty( ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{ca1765a7-b49a-417a-8f69-79710c56d8c5}maintenance_window_start'] ), ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{be98a17d-f7ec-4980-a5f6-84d775ba522f}maintenance_window_end'] <= ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{ca1765a7-b49a-417a-8f69-79710c56d8c5}maintenance_window_start'] ), "Window end date must be greater than or equal to the start date", "" ) } ), a!paragraphField( label: "Impact", labelPosition: "ABOVE", placeholder: "Any anticipated or possible impact of the maintenance", value: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{07cd91db-98f3-496c-ae45-a6ab2307a936}impact'], saveInto: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{07cd91db-98f3-496c-ae45-a6ab2307a936}impact'], refreshAfter: "UNFOCUS", characterLimit: 4000, height: "SHORT", required: true, validations: {} ), { a!columnsLayout( columns: a!columnLayout( contents: { a!richTextDisplayField( labelPosition: "COLLAPSED", value: { a!richTextItem( text: "Notification Recipients", style: "STRONG" ) } ), a!forEach( items: local!emailNotify, expression: { a!sideBySideLayout( items: { a!sideBySideItem( item: a!textField( label: "Email Address" & " " & fv!index, labelPosition: "COLLAPSED", placeholder: "group@google.com", value: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{3ceaa747-1816-40cd-af23-175364e4a157}distribution_list'], saveInto: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{3ceaa747-1816-40cd-af23-175364e4a157}distribution_list'], refreshAfter: "UNFOCUS", characterLimit: 255, validations: { a!validationMessage( message: "An email is required.", validateAfter: "UNFOCUS", showWhen: a!isNullOrEmpty(local!emailNotify) ) } ) ), a!sideBySideItem( item: a!richTextDisplayField( labelPosition: "COLLAPSED", value: { a!richTextIcon( icon: "times", altText: "Remove email address", link: a!dynamicLink( saveInto: a!save( local!emailNotify, remove(local!emailNotify, fv!index) ) ), linkStyle: "STANDALONE" ) }, showWhen: count(local!emailNotify) > 1 ), width: "MINIMIZE" ) }, alignVertical: "MIDDLE" ) } ), a!richTextDisplayField( labelPosition: "COLLAPSED", value: a!richTextItem( text: { a!richTextIcon(icon: "plus", altText: "plus"), " ", "Add Email Address" }, link: a!dynamicLink( saveInto: { a!save( local!emailNotify, append(local!emailNotify, " ") ) } ), linkStyle: "STANDALONE" ), accessibilityText: "Clicking this link will add another email address input above." ) }, width: "NARROW_PLUS" ) ) }, a!textField( label: "Contact for Schedule Conflict", labelPosition: "ABOVE", helpTooltip: "Please indicate who should be contacted if there is a conflict with the maintenance window", placeholder: "John Smith at js@google.com or 540-223-5555", value: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{c31dd065-3be5-4f79-84e1-e5b6e4c4f4f5}schedule_conflict'], saveInto: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{c31dd065-3be5-4f79-84e1-e5b6e4c4f4f5}schedule_conflict'], characterLimit: 255, showCharacterCount: false, required: true ), a!pickerFieldUsers( label: "Contact for Maintenance Issues", labelPosition: "ABOVE", helpTooltip: "Please indicate who users can contact with any issues encountered due to the maintenance.", placeholder: "Begin typing and select a user", maxSelections: 1, value: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{ce827301-150c-475e-b089-bea45202564d}contact'], saveInto: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{ce827301-150c-475e-b089-bea45202564d}contact'], required: true, validations: {} ) } ) } ) }, buttons: a!buttonLayout( primaryButtons: { a!buttonWidget( label: if(ri!isUpdate, "Save", "Create"), saveInto: if( ri!isUpdate, { a!save( target: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{3278b6f6-a848-47b1-b5ca-617108dff7fb}modifiedBy'], value: loggedInUser() ), a!save( target: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{9c47b74b-e9c8-4925-965c-8cffb467d3f8}modifiedOn'], value: now() ) }, { a!save( target: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{b7fc07a0-925a-44ea-9cea-0f527aa18a8c}createdBy'], value: loggedInUser() ), a!save( target: ri!record['recordType!{7d9361ec-02ed-440c-bf27-394115549bf4}OPS Maintenance Notifications 2.fields.{4b8cdb5e-1794-4b3d-9c4f-b0ed58db02ee}createdOn'], value: now() ) } ), submit: true, style: "SOLID", validate: true ) }, secondaryButtons: { a!buttonWidget( label: "Cancel", value: true, saveInto: ri!cancel, submit: true, style: "OUTLINE", validate: false ) } ) ) )
That is very interesting--I will definitely look at this. Thank you!
Got it - seems like you need to cache the email address for each text field in the loop into local!emailNotify at the index of the loop. Then add another save which combines the email address array into the record field.
Example: saveInto: { a!save(local!emailNotify[fv!index], save!value), a!save(ri!record[email field], touniformstring(local!emailNotify))}
saveInto: {
a!save(local!emailNotify[fv!index], save!value),
a!save(ri!record[email field], touniformstring(local!emailNotify))
}
The touniformstring function is also at the core of how the saves work in Stefan's blog post:docs.appian.com/.../fnc_conversion_touniformstring.html
The value parameter also gets a little tricky; it would be something like
value
index(local!emailNotify, fv!index, {})
or
index(split(ri!record[record field], ","), fv!index, {})