Is there any way to override method in dynamic form?
I've created a form from code (create Form, adding DataSource, etc. and then FormRun). The problem is with the datasource validation. In normal form (in the AOT) I'd use return true in validateWrite to prevent normal validation on table.
How I can achieve this only from code? (or more precisely: when I've only class to play with)
I think the FormBuild.addMethod is what you are looking for. Provide the FormBuildDatasource object as the third argument to the addMethod method.
Related
I want refresh a form from a class. I want the refreh after a insert() statemant. Is here a better solution for this problem.
Here is my code:
try {
do {
row++;
this.readRow(row, cells);
ttsbegin;
this.insert();
ttscommit;
type = cells.item(row+1, 1).value().variantType();
}
while (type != COMVariantType::VT_EMPTY);
<--------
After the while the insert is finished and at this position where I will the refresh.
Usually you would pass a reference of the form's data source you want to refresh to your class and then call research on it to refresh it so that your newly inserted records appear.
Alternatively, although IMHO not that clean, is to pass a buffer of that form's data source to your class and then (maybe after checking via isFormDataSource) access and refresh the data source via the buffer's dataSource method.
A third way would be to implement a dedicated method on your form solely for the purpose of refreshing the data source as described above. When creating the instance of your class you then pass a reference to your form so that you can call that method when needed.
Update: To see how to call a method defined on a form from a class see the class Tutorial_Apply and form Tutorial_Form_Apply which shows how to call the method applyText which is implemented on the form. Likewise, you could define a method refreshData which calls research on your data source.
I have a form which is used for automatic journal postings.
On that form I have a Ok command button and in closeOk method of the form I call the method from my datasource table.
In the JournalCheckPost class's infoResult() method I want to determine if the method is called from my form. I know that it can be done with caller methods but I don't know how exactly it should be done technically.
It is bad practice to make a method depend on where it is called from.
What you can do is to pass an extra parameter to the LedgerJournalCheckPost and infoResult can then check that. This can be done by introducing a boolean flag and a parm method.
I think, there can be many situations:
You want to pass some parameters from form
You want to manipulate the form (for example refresh datasource after action is complete)
Something other
But in all the cases depending on particular form is not a very good idea.
In first case you can set parameters from code using parm methods, or, better pass parameters using the Args class
In the second you can cast Args.caller to some interface that contain all the methods you want and manipulate the form using that methods (see \Classes\SysFormRun_doRe usages for example)
On a form data source (SalesLine) I have a validateWrite method, which in turn calls the super() method to call the validateWrite method on the SalesLine table, amongst other checks.
In the SaleLine table I have custom functionality for recording, and sometime stopping, data changes.
I don't want this functionality to be triggered when I write to SalesLine from my new form. Therefore I want to check a condition, within the validateWrite method on the SalesLine table, to find out if the validateWrite was called form my new form. This will allow me to skip the data change recording/stopping if the SalesLine write was called from my new form.
What is the correct approach?
I could create a boolean recordSaveChecks and set it before calling SalesLine.write(), but is there a better way?
Edit: To clarify, I do not have form specific custom verification to add, I have a system-wide verification (therefore sits on the SaleLine Table), which needs to be skipped when called from from 1 specific form.
The best option may be to move the customization that is form specific onto the form's data source rather than on the table itself. But if you true want to add form-specific code to the table, you can see an example in Tables\Address.update(), where it checks this.dataSource().formRun().name() to determine if it has been called from the relevant form.
You could put your code on the SalesLine DataSource in the ValidateWrite() method, before the super call Something like this:
ret = YourCheckGoesHere;
if(ret)
{
ret = super();
}
else
{
info("Why validation failed goes here");
}
return ret;
Then you've implemented the validation logic into Table not into the Form because you need the validation to be system wide but you need to prevent this validation when Insert/Update the record.
I think you can by override write() method of Form DataSource and use SalesLine.doInsert(); and SalesLine.doUpdate();
I have my form in my action:
$this->form = new SomeForm($this->data);
the form has a bunch of fields I don't need for one action but has stuff I need for another action. What is the best way to handle this? Create an individual form for each necessity or dynamically remove fields when I instantiate it as above?
Thanks
It sounds like you are doing a multi-part form.
I assume that you want to validate all the values submitted in your form, but just not save them.
Its sounds like you are doing an abstract form, so don't extend a base object form, rather extend BaseForm.
Don't unset the values, use the form to validate them, even if they're going to be used later.
They are saved to the form object, so you can use that to pass values to your next action, so this is helpful, plus they are validated.
Override doSave() in the form to save the objects of the form you want to save.
In my opinion for this case, extending the form to each need and applying, through the override of the setup, selectively the unset instruction, you get a code a little more readable and maintainable.
Does anybody know the logic behind making DataSourceSelectArguments sealed?
I've implemented a custom DataSource (and related classes) for some custom business objects and custom WebControls. When thinking in filters (like in a grid) I discovered that the DataSourceSelectArguments is sealed. Surely, I'm missing something. (Maybe the logic is related to the fact that is nonsense to ask the DB again, just for filtering?, just a guess.)
Sorry for the delay, I was on holydays. :)
The problem is that a DataBoundControl such as ListView has a SortExpression property, but not a FilterExpression. It is fine to implement a sortable grid/list with a ListView by means of a IButtonControl WebControl that fires a PostBack and a Command event. Then you use the SortExpression or the Sort method and pass a sort expression that will fill the DataSourceSelectArguments.SortExpression and pass it to the DataSource which can construct the apropiate SQL statement (in my case) to retrieve the Data from the DB. This allows for separation between the Data and the WebControl that displays it, IMHO.
Following this pattern I was about to implement a filter by filling an extra parameter object in my DataSourceSelectArguments with the requested filter and I will have called Sort, which would have passed this arguments object to the DataSource, where I would have constructed the appropiate select clause.
I've finally solve it by "coding" the filter information in the SortExpression, but I find it ugly (for the name, in the first place: sort != filter), and I was wondering if there's a more appropiate way of doing this or if I'm missing something that is more subtle.
Edit:
Maybe a better approach would be to override ListView's PerformSelect method and ask my own implementation of the DataSourceView if it can filter, then call a special ExecuteSelect method that accepts a special DataSourceSelectArguments with a filter object. Taking care not to do anything that will break when someone use the custom ListView with a non-enhanced DataSourceView, of course.
My guess is because the class is a dumb data transfer object merely used to pass arguments to a method.
This class itself doesn't have any operations defined on it, thus what sort of polymorphism would you expect? For example, the existing methods will only know about the properties of this class, which are all settable, so there's no need to override the properties. If you added new properties, they would get ignored.
For your own method, can you create your own Arguments class that just happens to have all the same properties?