Skip to main content

In 2021R1, I added a button to the Details grid in Bills and Adjustments.  Everything is working great.  I just cannot get the button to be greyed out when the other buttons are greyed out.

I can disable it so it will display a dialog that it is disabled if someone clicks it, but it just looks bad that it appears to be available.  

This code fires and enables/disables the button correctly, but I cannot change the visibility of it.

I suspect this might be something to do with a workflow on this screen?  However, in my installation of 2021R1, the workflow for this screen is not editable.  You can’t even create a new workflow.  I don’t even know if that would solve this for me, but either way, I’d like to grey out that button when it is not applicable.

Thanks!

Joe

 

make sure you are using the correct RowSelected event.

You want to use the one related to the data in the grid, ARTran I believe.

You are looking at the Invoice itself not the line detail. If you are needing data related to the Invoice you can still look at the Base.Document.Current to get that, but button in the grid should be modified within the context of the grids data.

That should resolve your issue.


Hi @joe21  You can do visibility based on the State Column property.

 

Please refer below link and hope this helps.

 


@Shawn Burt  Just gave that a try but still not greyed out.  Thanks for the tip though.  It was an easy thing to try out!


if you are willing to share the project I can take a look. Naveen’s technique should work too but its been a while since I played with that. If I remember correctly it requires a unbound dac extension to store the state as it has to be boolean.


Yea.  I just looked at the link Naveen shared.  It looks like that solution is based on setting the state of the button based on a value in the selected line in the grid.  I just want the button to be greyed out when the document is not editable.  That way the button is visible on when the other buttons on that grid are visible, so I am depending on the document header for the status.  Here’s my code:

using ICSAllocations.DAC;
using ICSAllocations.Helper;
using PX.Data;
using PX.Data.BQL;
using PX.Data.BQL.Fluent;
using System;

namespace PX.Objects.AP
{
// Acuminator disable once PX1016 ExtensionDoesNotDeclareIsActiveMethod extension should be constantly active
public class APInvoiceEntry_Extension : PXGraphExtension<APInvoiceEntry>
{

public PXAction<APTran> AllocateLine;
protected void allocateLine()
{

//this.Base.Actions.PressSave();

APTran currentItem = this.Base.Transactions.Current;

if (currentItem == null) return;

APTranExt itemExt = PXCache<APTran>.GetExtension<APTranExt>(currentItem);

if (itemExt.UsrAllocationID == null)
{
throw new Exception("You need to select an Allocation Template");
}

int itemCounter = 0;
int itemCount = 0;
decimal? balanceToAllocate = currentItem.CuryLineAmt;

foreach (var detail in SelectFrom<ICAllocationAccounts>.InnerJoin<ICAllocationCode>.
On<ICAllocationCode.allocationID.IsEqual<ICAllocationAccounts.allocationID>>.
Where<ICAllocationCode.allocationID.IsEqual<@P.AsInt>>.
View.Select(Base, itemExt.UsrAllocationID))
{
itemCount++;
}

this.Base.Transactions.Delete(currentItem);

ICAllocationCode code = SelectFrom<ICAllocationCode>.
Where<ICAllocationCode.allocationID.IsEqual<@P.AsInt>>.
View.Select(Base, itemExt.UsrAllocationID);


foreach (ICAllocationAccounts detail in SelectFrom<ICAllocationAccounts>.InnerJoin<ICAllocationCode>.
On<ICAllocationCode.allocationID.IsEqual<ICAllocationAccounts.allocationID>>.
Where<ICAllocationCode.allocationID.IsEqual<@P.AsInt>>.
View.Select(Base, itemExt.UsrAllocationID))
{

itemCounter++;

APTran newRow = this.Base.Transactions.Insert();

newRow.InventoryID = currentItem.InventoryID;

this.Base.Transactions.Cache.Update(newRow);

if (itemCount == itemCounter)
{
newRow.CuryLineAmt = balanceToAllocate;
}
else
{
newRow.CuryLineAmt = Math.Round((decimal)((detail.Percent / 100) * currentItem.CuryLineAmt), 2);
balanceToAllocate -= (decimal)newRow.CuryLineAmt;
}

if (currentItem.Qty != null && currentItem.Qty > 0)
{
newRow.Qty = Math.Round((decimal)((decimal)(detail.Percent / 100) * currentItem.Qty), 2);
}

if (code.DescriptionSource == DescriptionSourceType.FromDocument)
{
newRow.TranDesc = currentItem.TranDesc;
}
else
{
newRow.TranDesc = code.TranDescr;
}

newRow.BranchID = detail.BranchID;

if(newRow.InventoryID == null)
{
newRow.SubID = detail.AccountSubID;
}
else
{
newRow.TranDesc = currentItem.TranDesc;
}

this.Base.Transactions.Cache.Update(newRow);
}
}

#region Event Handlers
//protected virtual void _(Events.RowSelected<APInvoice> e)
//{
// APInvoice line = e.Row;
// if (line == null) return;

// if(line.VendorID != null && (line.Status == "H" || line.Status == "B"))
// {
// AllocateLine.SetEnabled(true);
// AllocateLine.SetVisible(true);
// }
// else
// {
// AllocateLine.SetEnabled(false);
// AllocateLine.SetVisible(false);
// }
//}
protected virtual void _(Events.RowSelected<APTran> e)
{
//APInvoice line = e.Row;
//if (line == null) return;

if (Base.Document.Current.VendorID != null && (Base.Document.Current.Status == "H" || Base.Document.Current.Status == "B"))
{
AllocateLine.SetEnabled(true);
AllocateLine.SetVisible(true);
}
else
{
AllocateLine.SetEnabled(false);
AllocateLine.SetVisible(false);
}
}

#endregion
}
}

This is from the ASPX

      <px:PXDSCallbackCommand Name="AllocateLine" Visible="false" CommitChanges="true" />
 

                <px:PXToolBarButton Key="cmdAllocateLine" Text="Allocate Line">
                  <AutoCallBack Target="ds" Command="AllocateLine" /></px:PXToolBarButton>
 

The program works.  Just the dang button visibility…

FYI, my code is what I have to do to get it to work based on my skill set.  If you cringe, feel free to make any suggestions.  HA!

 


Try this:

protected virtual void _(Events.RowSelected<APTran> e)
{
APTran line = e.Row;
if (line is null) return;

APInvoice invoice = APTran.FK.Invoice.FindParent(e.Cache.Graph, line);
if (invoice is null) return;

AllocateLine.SetEnabled((invoice.VendorID is object && (invoice.Status == "H" || invoice.Status == "B")));
AllocateLine.SetVisible((invoice.VendorID is object && (invoice.Status == "H" || invoice.Status == "B")));
}

 

Even better, I think this would accomplish the same thing using only e’s Graph:

protected virtual void _(Events.RowSelected<APTran> e)
{
APTran line = e.Row;
if (line is null) return;

// Cast e's Graph as APInvoiceEntry and load parent Invoice
var apInvoiceGraph = e.Cache.Graph as APInvoiceEntry;
APInvoice invoice = apInvoiceGraph.Document.Current = apInvoiceGraph.Document.Search<APInvoice.docType, APInvoice.refNbr>(line.TranType, line.RefNbr);
if (invoice is null) return;

// Get APInvoiceEntry's Graph extension
var apInvoiceGraphExt = apInvoiceGraph.GetExtension<APInvoiceEntry_Extension>();

// Enable / disable custom Action
apInvoiceGraphExt.AllocateLine.SetEnabled((invoice.VendorID is object && (invoice.Status == "H" || invoice.Status == "B")));
apInvoiceGraphExt.AllocateLine.SetVisible((invoice.VendorID is object && (invoice.Status == "H" || invoice.Status == "B")));
}

 


@darylbowman  Button kicks a dialog that the button is disabled, so at least the code will not fire.

But unfortunately, the button is still allowing me to click it.  :-(

Thank you so much for the code though.  It is another way of doing it that I can keep for future reference.  

You guys have been super quick with stuff to try.  I can’t thank you all enough.  This is not the end of the world so it’s ok to just let it be.  I was thinking this was just another dumb thing I was missing, but I think that there is some overriding forces at work that I probably cannot work around.

You guys rule!

Thank you!


@joe21 Try the second option


@darylbowman HAHA!  I love the persistence!  I literally spent 2 hours trying to find a way to get this to work.  I love the fact there are others out there who refuse to give up!  Ha!

Got a compiler error.  From what I can see, this error seems erroneous.  I tried to build it anyway just to see if it was one of those Acumatica warnings that wasn’t actually going to stop the code from running but it doesn’t compile.

Please don’t waste any more of your time on this.  It is just a “presentation” issue that the customer can live with.  You are making me feel guilty!


My bad. Change

var apInvoiceGraphExt = invoice.GetExtension<APInvoiceEntry_Extension>();

to

var apInvoiceGraphExt = apInvoiceGraph.GetExtension<APInvoiceEntry_Extension>();

 

I don’t have that extension so VS didn’t catch that.


I did a RESTART APPLICATION to make sure all caches were re-instantiated.  I then went into debug and verified that the code was being hit.  The Status is “K” so the properties were being set to False.

Still, the evil button is visible.  

If my customer makes a big deal about this, would this be something I should submit as a “trouble ticket” to Acumatica?  I’ve got some great minds looking at this and maybe in 2021R1, it is just not possible to change that field status.  I have seen a few things in the new product that does not work the same way it did in older versions.


Hi @joe21 You might tried all possible ways, have you tried with the Workflow automation steps from the customization project and verified?

 

 


Ok, so thinking back through this, your conditions are all Invoice specific, not row specific, so there should be no need to use APTran. Since it is disabled for all rows, I don’t think there would be a need to tie it into the grid either. Try this yet:

protected virtual void _(Events.RowSelected<APInvoice> e)
{
APInvoice invoice = e.Row;
if (invoice is null) return;

// Cast e's Graph as APInvoiceEntry and load parent Invoice
var apInvoiceGraph = e.Cache.Graph as APInvoiceEntry;
invoice = apInvoiceGraph.Document.Current = apInvoiceGraph.Document.Search<APInvoice.docType, APInvoice.refNbr>(invoice.DocType, invoice.RefNbr);

// Get APInvoiceEntry's Graph extension
var apInvoiceGraphExt = apInvoiceGraph.GetExtension<APInvoiceEntry_Extension>();

// Enable / disable custom Action
apInvoiceGraphExt.AllocateLine.SetEnabled(invoice.VendorID is object && (invoice.Status == "H" || invoice.Status == "B"));
apInvoiceGraphExt.AllocateLine.SetVisible(invoice.VendorID is object && (invoice.Status == "H" || invoice.Status == "B"));
}

It does not appear that you can add a new workflow to this screen

 

SO...I tried the other suggestion you provided above. I used the UsrAllocationID field as the StateColumn.

                <px:PXToolBarButton Key="cmdAllocateLine" Text="Allocate Line" DependOnGrid="grid" StateColumn="UsrAllocationID">
                  <AutoCallBack Target="ds" Command="AllocateLine" /></px:PXToolBarButton>

 

It worked!!  Since the Allocation ID field in the grid is disabled when the other fields are disabled, the button only lights up when you are able to select an allocation ID.

Seems like the VS code should work.  But I guess you have to do it the way they want you to do it.

Thanks guys for your support!

 

 


@darylbowman Exactly what I thought.  I tried it both ways.  The only way I could get it to work was with the StateColumn on the <px:PXToolBarButton aspx.

The way I have it set now actually works better because the button will only light up when there is an allocation ID selected.


@nmansinha - Any insight here? You’re a wizard with these things.


@nmansinha - Any insight here? You’re a wizard with these things.

Just want to make sure you don’t invest any more time into this.  The Naveen suggestion did solve my issue.  It actually works better than my original plan because the button is available not only based on the status of the document, but whether or not the Allocation ID field has a value.  

Still curious as to why our VS code was being ignored though.  :-)


Still curious as to why our VS code was being ignored though.  :-)

This


I suspect your code was working but the workflow engine was re-enabling the action. You can modify the workflow via code(even ones that are disabled from editing in the customization editor).

Using a graph extension and overriding the Configure method allows you to do so. There is a relatively new training available on it:

https://openuni.acumatica.com/courses/development/t270-workflow-api/


Reply