I am trying to create a Repeater Template User Control i.e. a rectangular border contains a row of UIElements Like TextBox, ComboBox etc and then I'm automatically adding a + button at the end of the Row. On + button Click I want to add the Same duplicate row below it.
This is the Syntax making use of User Control:
<RepeaterTemplate>
<RepeaterTemplateItem>
<TextBox />
<ComboBox />
</RepeaterTemplateItem>
</RepeaterTemplate>
CODE BEHIND:
RepeaterLayoutItem:
Public Grid RepeaterRow { get; set; }
Public List LayoutItemCollection { get; set; }
//On + button click handler:
RepeaterLayoutItem duplicate = this.memberWiseClone();
LayoutItemCollection.Add(duplicate);
RepeaterLayout :
public ObservableCollection Children { get; set; }
public Grid RepeaterContentGrid { get; set; }
foreach(RepeaterLayoutItem item in Children)
{
Grid duplicateRow = item.RepeaterRow;
RepeaterContentGrid.Children.Add(duplicateRow); //Here it gives error "Element is already child of other element" on + button click.
}
I also tried it with ICloneable interface, but still same issue.
If I duplicate the row using the memberWiseClone(), still on adding the duplicate row I'm getting the same error. May be bceause of non-null value of Parent property in the cloned duplicate row.
I don't know how to get this functionality working. Please HELP.
Thanks,
GK Prajapati
Related
I need to open telerik blazor date range picker on calendor Icon click.
I was tried to find the solution but can not able to find proper that is work for me.
The telerik document have no such event to take care of it on different control click or may be I missed that. Can someone please help me with the same.
I tried to recall the DateRangePickerOpenEeventtArgs but not able to achieve it.
Thanks in advance!!
I found my answer in telerik document itself.
We need to create a refType of TelerikDateRangePicker like below:
<TelerikButton OnClick="#OpenPicker">Open DateRangePicker</TelerikButton>
<TelerikDateRangePicker #ref="#DateRangePickerRef"
#bind-StartValue="#DateRangePickerStartValue"
#bind-EndValue="#DateRangePickerEndValue" />
#code {
// the component type depends on the value type, could be also DateTime?
private TelerikDateRangePicker<DateTime> DateRangePickerRef { get; set; }
private DateTime DateRangePickerStartValue { get; set; } = DateTime.Now;
private DateTime DateRangePickerEndValue { get; set; } = DateTime.Now.AddDays(10);
void OpenPicker()
{
DateRangePickerRef.Open();
}
}
So that reference directly hit our control from methods.
ref link : telerik blazor date range event handling
I have implemented CRM activity on the Custom page where the Key Field is SOOrder Type, SOOrder Nbr & Job Code which are stored in custom DAC. I have tried to add the Entity Type listed on Related Entity and I am not able to figure out how to do it. Pls let me know where to add or override the method to Implement the functionality
The following cod used to implement the CRM Activity
public sealed class SOOrderJobActivities : CRActivityList<PSSOOrderJob>
{
public SOOrderJobActivities(PXGraph graph)
: base(graph) { }
protected override RecipientList GetRecipientsFromContext(NotificationUtility utility, string type, object row, NotificationSource source)
{
var recipients = new RecipientList();
var order = _Graph.Caches[typeof(PSSOOrderJob)].Current as PSSOOrderJob;
if (order == null || source == null)
return null;
SOOrder ord = SOOrder.PK.Find(_Graph, order.OrderType, order.OrderNbr);
var contact = SOOrder.FK.Contact.FindParent(_Graph, ord);
if (contact == null || contact.EMail == null)
return null;
recipients.Add(new NotificationRecipient()
{
Active = true,
AddTo = RecipientAddToAttribute.To,
Email = contact.EMail
});
source.RecipientsBehavior = RecipientsBehaviorAttribute.Override;
return recipients;
}
}
Update
After going through the Acumatica code, I have done the following changes
#region Noteid
[PXNote(ShowInReferenceSelector =true,Selector =typeof(Search2<PSSOOrderJob.jobCode,
InnerJoin<SOOrder,On<PSSOOrderJob.orderType,Equal<SOOrder.orderType>,And<PSSOOrderJob.orderNbr, Equal<SOOrder.orderNbr>>>>,
Where<SOOrder.orderType,Equal<Current<PSSOOrderJob.orderType>>,And<SOOrder.orderNbr, Equal<Current<PSSOOrderJob.orderNbr>>>>>))]
public virtual Guid? Noteid { get; set; }
public abstract class noteid : PX.Data.BQL.BqlGuid.Field<noteid> { }
#endregion
The entity comes into selection, But I am not able to select the relative entity document and the value is not getting updated in the related entity field.
The above screenshot the select is missing and not able to select the document
The following steps I have done to add relative Entity for any Activity using custom DAC
1. Added ShowInReferenceSelector = true in PXNoteID field.
2. Added Selector in PXNoteID field
3. Decorated [PX.Data.EP.PXFieldDescription] attribute for Key fields
#region NoteID
[PXNote(ShowInReferenceSelector = true, Selector = typeof(Search2<PSSOOrderJob.jobCode,
InnerJoin<SOOrder, On<PSSOOrderJob.orderType, Equal<SOOrder.orderType>, And<PSSOOrderJob.orderNbr, Equal<SOOrder.orderNbr>>>>,
Where<SOOrder.orderType, Equal<Current<PSSOOrderJob.orderType>>, And<SOOrder.orderNbr, Equal<Current<PSSOOrderJob.orderNbr>>,And<PSSOOrderJob.jobType,Equal<Current<PSSOOrderJob.jobType>>>>>>), DescriptionField = typeof(PSSOOrderJob.jobCode))]
//[PXNote(ShowInReferenceSelector = true)]
public virtual Guid? NoteID { get; set; }
public abstract class noteID : PX.Data.BQL.BqlGuid.Field<noteID> { }
#endregion
#region JobCode
[PXDBString(15, IsKey = true, IsUnicode = true, InputMask = ">CCCCCCCCCCCCCCC")]
[PXUIField(DisplayName = "Job Code")]
[PXDefault()]
[PXSelector(typeof(Search<PSSOOrderJob.jobCode, Where<PSSOOrderJob.orderType, Equal<Current<PSSOOrderJob.orderType>>, And<PSSOOrderJob.orderNbr, Equal<Current<PSSOOrderJob.orderNbr>>,And<PSSOOrderJob.jobType, Equal<Current<PSSOOrderJob.jobType>>>>>>), typeof(PSSOOrderJob.jobCode), ValidateValue = false)]
[PSSOOrderJobNbr.Numbering()]
[PX.Data.EP.PXFieldDescription]
public virtual string JobCode { get; set; }
public abstract class jobCode : PX.Data.BQL.BqlString.Field<jobCode> { }
#endregion
This automatically fills the related entity field with Jobcode.
There still one issue I am facing is not able to access the selector due to Entity field width is more than the popup window and I do not know how to fix it.
This answer is to address the popup size only.
First, give browser zoom a try 'control' + 'minus' key. It might work as a quick workaround.
Otherwise, use the browser debugger feature. Open it with F12 key. Then use the browser debugger inspect element feature (1). Click on the smart panel (2). Go up a bit in html control hierarchy until you reach and select the smart panel root which is a table element (3). Change the width of the smart panel popup using the debugger CSS properties editor (4).
If selector control size increases automatically with window size; change the selector control width instead of popup width using browser debugger CSS property editor.
I have 2 scenarios, I am facing issue.
I have 3 DAC, One is Parent and other 2 are child DAC.
I have tab view, and showing data accordingly.
First tab showing Parent DAC data.
Second and third are showing child DAC data.
I am creating new item, Now i press Add(+) button and fill, Information in Parent tab, but not filled any data in 2nd and 3rd tab, when i press SAVE then only parent DAC saved, 2nd and 3rd tab rows not created in database, I want to save 2nd and 3rd Tab DAC also, what should i do?
Another case:
i am not allowing DAC to update, I am setting DAC.Cahce.AllowUpdated = false; all controls are disabled excepting Checkbox, why?
Also when we are on 3rd tab and click on toolbar Navigation button, then 1st tab data doesn't refresh, it is showing previous selected item data. How to fix this issue?
We are not using PXGrid for any child data, there is one to one relation ship between all 3 DAC.
/// Parent View
public SelectFrom<Parent>.View parentTran;
/// Child view
public SelectFrom<Child> .Where<Child.tranId.IsEqual<Parent.nCTranId.AsOptional>>.View
childAnalysis;
#region TranId
// Child DAC Field.
public abstract class tranId:PX.Data.BQL.BqlInt.Field<tranId> {
}
[PXDBInt(IsKey = true)]
[PXDBDefault(typeof(Parent.nCTranId))]
[PXParent(typeof(Select<Parent, Where<Parent.nCTranId, Equal<Current<tranId>>>>))]
public virtual int? TranId {
get; set;
}
#endregion
Take a look at T210 regarding Master-Detail Relationships. It contains a section on inserting a default record, which sounds like what you are trying to do with your child DAC. The training can be found at https://openuni.acumatica.com/courses/development/t210-development-customized-forms-and-master-detail-relationship/ on the Acumatica website. Specifically look at pages 103 and 104.
In step 3 of the section, you will see use of the RowInserted event to insert the child record. Since the RowInserted event fires only when creating a record, making it safe to insert the child record.
See the following code sample. I tried to use as much of your sample as possible, but I merged it with the technique shown in the training guide. Disclaimer: It will compile, but I have not built the prerequisites to fully test the code.
using PX.Data;
using PX.Data.BQL.Fluent;
namespace SSCS.CodeSample
{
public class CodeSampleEntry : PXGraph<CodeSampleEntry, DACParent>
{
#region Data Views
/// Parent View
[PXViewName("Parent View - Primary")]
public SelectFrom<DACParent>.View ParentTran;
/// Child view
[PXViewName("Child View")]
public SelectFrom<DACChild>
.Where<DACChild.tranId.IsEqual<DACParent.nCTranId.FromCurrent>>
.View ChildAnalysis;
#endregion
// RowInserted Event to Create a Default Child Record
// See T210 Master-Detail training guide from Acumatica
protected virtual void _(Events.RowInserted<DACParent> e)
{
// Ensure there isn't a child record already
if (ChildAnalysis.Select().Count == 0)
{
// Save state of IsDirty so that we can restore it
// after inserting the default child record
// so that we don't force the user to save
// unless they actually enter data somewhere
bool oldDirty = ChildAnalysis.Cache.IsDirty;
// Create an object for the child
// and fill in any data that should be
// populated by default
DACChild newChild = new DACChild();
newChild.MyData = "My Value";
// Insert the new child record into the cache
ChildAnalysis.Insert(newChild);
// Restore the IsDirty flag
// The insert above will have marked the view as
// dirty. If it wasn't dirty before, it should be
// treated as if it still isn't
ChildAnalysis.Cache.IsDirty = oldDirty;
}
}
}
[PXCacheName("Parent DAC")]
public class DACParent : IBqlTable
{
#region NCTranId
[PXDBIdentity]
public virtual int? NCTranId { get; set; }
public abstract class nCTranId
: PX.Data.BQL.BqlInt.Field<nCTranId> { }
#endregion
}
[PXCacheName("Child DAC")]
public class DACChild : IBqlTable
{
#region TranId
[PXDBInt(IsKey = true)]
[PXDBDefault(typeof(DACParent.nCTranId))]
[PXParent(typeof(SelectFrom<DACParent>
.Where<DACParent.nCTranId.IsEqual<DACChild.tranId.FromCurrent>>))]
public virtual int? TranId { get; set; }
public abstract class tranId
: PX.Data.BQL.BqlInt.Field<tranId> { }
#endregion
#region MyData
[PXDBString()]
[PXUIField(DisplayName = "My Data Field")]
public virtual string MyData { get; set; }
public abstract class myData
: PX.Data.BQL.BqlString.Field<myData> { }
#endregion
}
}
Is there a way to display row numbers in Acumatica grid? You could display LineID; however, when you sort your columns the LineID's will of course become scrambled.
Thanks,
There are two possible cases:
1. you need to add row numbers to existing screen
2. you need to add row numbers to your screen
For case 1 consider that you want to add row numbers to page po301000, tab Document details. The grid in tab Document details is binded to DataMember Transactions as you can see on screenshot fragment:
Second part of puzzle is graph, which you need to extend. As you can see from screenshot you need to extend PX.Objects.PO.POOrderEntry:
Third part that you'll need is extending of POLine. You can achieve it with following sample of code:
public class POLineExt : PXCacheExtension<POLine>
{
public abstract class rowNumber : IBqlField
{
}
[PXInt]
public int RowNumber { get; set; }
}
and extend graph like this:
public class POOrderEntryExt : PXGraphExtension<POOrderEntry>
{
public PXSelect<POLine, Where<POLine.orderType, Equal<Current<POOrder.orderType>>, And<POLine.orderNbr, Equal<Optional<POOrder.orderNbr>>>>, OrderBy<Asc<POLine.orderType, Asc<POLine.orderNbr, Asc<POLine.lineNbr>>>>> Transactions;
protected IEnumerable transactions()
{
var result = Base.Transactions.Select();
int rowNumber = 1;
foreach (PXResult<POLine> lineBoxed in result)
{
var line = lineBoxed.GetItem<POLine>();
var lineExt = line.GetExtension<POLineExt>();
lineExt.RowNumber = rowNumber;
rowNumber++;
}
return result;
}
And the final part, you'll need to add your customized column on your page:
<px:PXGridLevel DataMember="Transactions">
<Columns>
<px:PXGridColumn DataField="RowNumber" Width="80px"></px:PXGridColumn>
After all of this I've seen the following on mine page purchase orders:
Second case is very similar to first described here, just with difference that you don't need to extend anything.
In Sales Order documents grid footer. It displays the product's availability.
How to do the same in Opportunity products grid ?
More so, how do you enforce it to be displayed at the footer
instead of a simple grid column ? Is there such attribute ?
Thanks for the replies.
If we compare to sales order, the sales order line gets its value from LSSOLine during Availabilty_FieldSelecting. The wire-up on the page is on the tab via StatusField="Availability". We can do something similar by adding an unbound extension field and then during a field selecting fill in the value. An alternative would be to implement an LSCROpportunityProducts class that is inherits LSSelect similar to LSSoLine (a better preferred solution). To keep this simple and focus on just getting the field to display text, I will use an extension field and a simple field selecting in the extension graph for opportunity.
(1) In a dac extension, create an unbound field (MyAvailability is the example field):
[PXTable(typeof(CROpportunityProducts.cROpportunityID), typeof(CROpportunityProducts.cROpportunityProductID), IsOptional = true)]
[Serializable]
public class CROpportunityProductsMyExtension : PXCacheExtension<CROpportunityProducts>
{
#region MyAvailability
public abstract class myAvailability : PX.Data.IBqlField
{
}
protected string _MyAvailability;
[PXString(IsUnicode = true)]
[PXUIField(DisplayName = "Product Availability", Enabled = false)]
public virtual string MyAvailability
{
get
{
return this._MyAvailability;
}
set
{
this._MyAvailability = value;
}
}
#endregion
}
(2) On the opportunity products tab, wire up the new field as the grid status value by setting property StatusField. The page needs modified to add this value and should look something like this when added (requires screen customization in your project -> actions edit ASPX and locate ProductsGrid to paste in your StatusField and value):
<px:PXGrid ID="ProductsGrid" SkinID="Details" runat="server" Width="100%"
Height="500px" DataSourceID="ds" ActionsPosition="Top" BorderWidth="0px"
SyncPosition="true" StatusField="MyAvailability">
(3) Now in a graph extension populate the field:
Edit: The use of Current<> does not always contain the correct currently highlighted row in the UI. Switched to Required<> based on the PXFieldSelectingEventArgs.Row and the results are correct for multiple rows in the products tab.
public class CROpportunityMaintMyExtension : PXGraphExtension<OpportunityMaint>
{
public virtual void CROpportunityProducts_MyAvailability_FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
{
var row = (CROpportunityProducts) e.Row;
if (row == null)
{
e.ReturnValue = string.Empty;
return;
}
INLocationStatus locationStatus = PXSelectGroupBy<INLocationStatus,
Where<INLocationStatus.inventoryID, Equal<Required<CROpportunityProducts.inventoryID>>,
And2<Where<INLocationStatus.subItemID, Equal<Required<CROpportunityProducts.subItemID>>,
Or<Not<FeatureInstalled<PX.Objects.CS.FeaturesSet.subItem>>>>,
And<Where<INLocationStatus.siteID, Equal<Required<CROpportunityProducts.siteID>>,
Or<Required<CROpportunityProducts.siteID>, IsNull>>>>>,
Aggregate<Sum<INLocationStatus.qtyOnHand, Sum<INLocationStatus.qtyAvail>>>
>.Select(sender.Graph, row.InventoryID, row.SubItemID, row.SiteID, row.SiteID);
// Need to convert to transaction UOM... (this is always base units)
decimal? qtyOnHand = locationStatus?.QtyOnHand;
decimal? qtyAvail = locationStatus?.QtyAvail;
e.ReturnValue = $"Qty On hand = {qtyOnHand.GetValueOrDefault()} ; Qty Avail = {qtyAvail.GetValueOrDefault()}";
}
}
The results: