Apologies this is a long one.
Customizations added:
- Custom field added via ARTranExt for field “SomeField” of type string
- Custom field added via ARRegisterExt for field “SomeFieldChanged” of type boolean
- Custom action “EnableSomeField” added on the Action menu
What I’m trying to achieve:
- When a user opens an existing invoice, ARTranExt.SomeField must not be editable
- When the user clicks the EnableSomeField action, only SomeField must become editable. I set a property calleld “editMode” to true
- When the user selects an ARTran row, in Event.RowSelected<ARTran>, I check if editMode is true, and if yes, enable ARTranExt.SomeField
- In Events.RowUpdated<ARTran>, I check if currentRow.SomeField == oldRow.SomeField, and if not, I set ARRegisterExt.SomeFieldChanged to true
The code:
public class ARInvoiceEntry_Extension : PXGraphExtension<ARInvoiceEntry>
{
private bool editMode = false;
public override void Initialize()
{
base.Initialize();
base.Base.ActionsMenuItem.AddMenuAction(this.ChangeIntegrationFields);
}
#region Actions
public PXAction<ARInvoice> ChangeIntegrationFields;
[PXButton(CommitChanges = true)]
[PXUIField(
DisplayName = "Change Integration Fields",
Enabled = false,
Visible = true,
MapEnableRights = PXCacheRights.Update,
MapViewRights = PXCacheRights.Update)]
protected virtual void changeIntegrationFields()
{
this.editMode = true;
}
#endregion
#region Event Handlers
protected virtual void _(Events.RowSelected<ARInvoice> e)
{
ARInvoice invoice = e.Row;
if (invoice == null) return;
this.ChangeIntegrationFields.SetEnabled(true);
e.Cache.AllowUpdate = true;
base.Base.Transactions.Cache.AllowUpdate = true;
}
protected virtual void _(Events.RowSelected<ARTran> e)
{
ARTran artran = e.Row;
if (artran == null) return;
if (this.editMode) this.EnableFields(e.Cache, artran, true);
}
private void EnableFields(PXCache cache, ARTran row, bool enableFields)
{
// Set all fields to readonly and disabled
PXUIFieldAttribute.SetReadOnly(cache, row, true);
PXUIFieldAttribute.SetEnabled(cache, row, false);
// Set specific fields to editable
PXUIFieldAttribute.SetReadOnly<ARTranExt.someField>(cache, row, !enableFields);
PXUIFieldAttribute.SetEnabled<ARTranExt.someField>(cache, row, enableFields);
}
protected virtual void _(Events.RowUpdated<ARTran> e)
{
var artran = (ARTran)e.Row;
var oldartran = (ARTran)e.OldRow;
if (artran == null || oldartran == null) return;
ARTranExt artranext = artran.GetExtension<ARTranExt>();
ARTranExt oldartranext = oldartran.GetExtension<ARTranExt>();
if (IntegrationFieldsChanged(artranext, oldartranext))
{
var currentInvoice = base.Base.CurrentDocument.SelectSingle();
base.Base.Caches[typeof(ARRegister)]
.SetValue<ARRegisterOIFExt.someFieldChanged>(
currentInvoice, true);
}
}
private bool IntegrationFieldsChanged(ARTranExt oldRow, ARTranExt newRow)
{
if (oldRow.SomeField != newRow.SomeField) return true;
return false;
}
#endregion
}
Problem I’m having:
- When the user opens the document SomeField is already editable, I believe this is because of the .AllowUpdate properties I’m settings to true in Event.RowSelected<ARInvoice>, which makes sense according to the summary description on the properties.
- Problem is when I add logic for that, i.e. setting the .AllowUpdate’s to true only if EditMode is true, then it doesn’t seem to take affect. When changing SomeField and saving the data isn’t persisted to the database and the UI reverts back to the previous values. Is there a reason why it would take affect after the page has already rendered and the user then clicks the button which would execute that part of the logic?
- Also by setting the .AllowUpdate properties to true, if I understand correctly I’m setting everything in the cache to editable, then in EnableFields() I’m first disabling all the UI fields again and then only enabling the one’s I want to be updated, it seems a bit convoluted. Is there a better approach for this can only make the specific fields in the cache updateable and not touch the rest of them?
I minimized the amount of custom fields to try and keep it shorter, but the idea is to implement this exact same customization on ARInvoiceEntry, APInvoiceEntry and JournalEntry.
I did the dev training where that whole Phoneshop is built, but I searched through that solution and I can’t find that .Cache.AllowInsert/Update/Delete, etc. so unless I completely missed it I don’t think it was touched on, so I’m unsure if this is even the correct approach. I’m rambling now sorry.