I'm currently working on a form in Microsoft Dynamics AX.
The form consists of a grid with about 10 fields from 4 different tables.
As the form is now it returns too many values so I need to include some sort of filter, it doesn't need to be dynamic, just a static filter saying only show the lines with value X in column Y.
Has anyone here got some experience with this sort of thing? Where do I start?
I must say I'm not experienced with Microsof AX at all, I've been working with it for about a month now.
I've tried to follow this guide: How to: Add Filter Controls to a Simple List Form [AX 2012]
But I got stuck at the second part (To add a control to the custom filter group) Step 2: I dont know which type of control to chose, and ik i pick lets say a ComboBox i cant get Step 3 to work because I dont see the 'Override Methods' they mention.
Well, I usually do it this way:
In ClassDeclaration, create as many QueryBuildRanges variables as fields to filter. Let's name them Criteria1, Criteria2, etc (name them properly, please, not as here)
QueryBuildRange criteria1, criteria2;
In each Datasource you need to filter, override method Init, an add code similar to this:
super();
criteria1 = this.query().datasource(tablenum(tableofdatasource)).addQueryRange(fieldNum(fieldtofilter))
//criteria1.status(RangeStatus::locked); //optional - this way you can hide filter field to user, have it readonly for users, etc
Create a control of type StringEdit or ListBox in form to be used as filter. Change their AutoDeclaration property to Yes. Override modified() method. In it, I use to put something similar to:
super();
element.changeFilters();
In form, add method changeFilters();
range rangeFromStringControl = StringEditControlName.text(); //Put in rangeFromStringControl the string to be used as filter, as a user would write it
range rangeFromListBoxControl;
criteria1.value(rangeFromStringControl);
switch (listBoxControl.Selection())
{
case NoYesAll::All:
rangeFromListBoxControl = ''; //Empty filter string - No filter at all
break;
case NoYesAll::No:
rangeFromListBoxControl = QueryValue(NoYes::No); //Or whatever string filter value you want
break;
//Etc
}
//We have all filter strs done; let's filter for each main DataSource required with new filters
DataSource1.executeQuery();
//If there is other datasources joined to this one, it's usually no necessary to call their executeQuery;
//If there are others with filters and not joined to it, call their executeQuery()
If you need this filter to be applied when form is open, set appropiate initial values to controls, and then in form's run() method:
run();
element.changeFilters();
Related
I am trying to automate text boxes to fill with a certain value, however the text boxes names are not static so they will always change. I am looking to find a way to always populate them even though they do not have a static name and how to find the second, third, fourth etc instance of the boxes and be able to also fill them without overwriting the previous text boxes
i have tried using the _collect function in sahi pro but could not find how to target the class correctly
I expect to be able to populate any textbox using the same class name without overwriting the first instance of this class.
I am using Sahi pro.
The sahi documentation on _collect seems to be you exactly what you are looking for
// Collect all textboxes matching any identifier, in table "listing".
// Note the use of match all regular expression "/.*/"
var $textboxes = _collect("_textbox", "/.*/", _in(_table("listing"));
// Iterate and set values on all textboxes
for (var $i=0; $i<$textboxes.length; $i++) {
_setValue($textboxes[$i], "value");
}
If this does not solve your problem, please provide an example of the html and of your _collect code
I have a form that has some labels repeated, but in different subsections. Here's an example of part of my form:
I want to be able to choose, for example, the Days from Section A and also the Days from Section B independently. To that end, I've tried using the getByLabelText method:
it('should display correct value for days field', async () => {
const {getByLabelText} = render(<MyForm/>);
const daysElement = await waitForElement(() =>
getByLabelText(/Days/i) as HTMLInputElement
);
expect(daysElement.value).toEqual('0');
});
I'm using htmlFor on the label for Days and a matching Id on the associated input element. Each section has a context provided to disambiguate the otherwise matching Ids (e.g. for days). For example:
<Field label={i18n.days} htmlFor={`${name}_days`} value = {<NumberControl name='days' id={`${name}_days`} value={this.state.days}}/>
In this code, ${name} would resolve to something that is different for section A vs section B. (Field and NumberControl would ultimately create label and input elements, setting htmlFor and id values appropriately).
When I use getByLabelText as illustrated above, it obtains the value for Section A. But I also need to obtain the value for Section B. How would I do this?
You have different options depending on your DOM structure.
If you have a way to query your section—for example with a data-testid—you could use within:
within(getByTestId('id-for-section-A')).getByLabelText('Days')
within(getByTestId('id-for-section-B')).getByLabelText('Days')
within gives you all the query helpers that are returned by render but they are limited to the children of the node you pass to them.
If you can't add a data-testid to your section but you're always sure about the order in which the fields appear on the page you can use getAllByLabelText:
const [firstInput, secondInput] = getAllByLabelText('Days')
Lastly, if none of the above works, you could use the id attributes since they are unique. renderd returns a container element which is just a DOM Node. You can use the regular DOM methods on it:
const { container } = render(<YourForm />)
container.getElementById('section_A_days')
container.querySelector('#section_A_days')
How you query within your container depends on your DOM structure.
I personally would go with within but it very much depends on your use-case.
Let's say I've the following class:
class Person(object):
def __init__(self, attributes):
# Attributes is just a dictionary (string -> value)
self.attributes = attributes
def set_attribute(self, attribute, value):
self.attributes[attribute] = value
# Some other code which may cause the value of other attributes to change,
# or other attributes to be added or deleted too
Now I'd like to create a PyQt dialog with a simple form, but which is dynamically generated (to account for the variable number of attributes). I did this by creating a QFormLayout in a QDialog and adding a row for every attribute the Person object has:
self.formLayout = QtWidgets.QFormLayout()
for attribute in self.person.attributes.keys():
label = QtWidgets.QLabel(self)
label.setText(attribute)
lineEdit = QtWidgets.QLineEdit(self)
lineEdit.textEdited['QString'].connect(self.onAttributeChanged)
# or use a checkbox instead of a line edit if the attribute is a boolean,
# combo box if it's an enum or similar, etc.
self.formLayout.addRow(label, lineEdit)
Where onAttributeChanged() calls self.person.set_attribute with the appropriate attribute and the new value inputted by the user.
Now that takes care of updating the model with the user's input values, but the problem I'm facing is how to update the view when set_attribute modifies the person's other attributes (since set_attribute may add or delete other attributes, or change the other attributes' names or values). So far, I've considered to following:
Rebuild the entire form whenever information changes. There's probably something better than this.
Use the Qt signal/slot model, like I did by connecting lineEdit to onAttributeChanged. From what I understand, this means using pyqtSignal to create signals in my Person class representing the attribute names, plus emitting the appropriate signals whenever the names are modified. However, I'd like to keep my Person class intact, and free from any Qt .emit() calls. (Not to say this still doesn't handle the case of attributes being added/removed.)
Ditch the form altogether and use a table view with a QStandardItemModel instead. Not ideal since I really wanted a form and not a table (for the sake of better usability).
Is there some elegant way of handling this kind of dynamic form in PyQt?
I have a form with 2 elements that will be submitted and then update part of a user profile.
I don't want to use the entire generated form and have to remove all the fields except for the two I need. I just want to be able to create a quite simple form to do my update.
Is there a way to utilize Symfony's sfValidatorEmail inside the action on the returned value of an email field?
Since the regex is already written in the validator, I would like to reuse it, but I don't know how to use it in the action after the non-symfony form has been submitted.
Two approaches here - you could construct a simple form anyway extending from sfForm/sfFormSymfony (doesn't have to be ORM-based) that just contains the 2 fields you want. That way you can use the existing validation framework, and then use $myForm->getValues() after everything has been validated to get your values for your profile update.
Alternatively, as you've mentioned, you can use the sfValidatorEmail class in your action like so:
$dirtyValue = "broken.email.address"
$v = new sfValidatorEmail();
try
{
$v->clean($dirtyValue);
}
catch (sfValidatorError $e)
{
// Validation failed
}
The latter approach quickly leads to messy code if you have many values that need cleaning, and it's worth putting the logic back into a form to handle this in the usual manner.
If you're submitting a form with 2 elements, it should be a form on the edit and update end, period. Symfony forms are lightweight, there's no performance reason to not use them. Instead, make a custom form for this purpose:
class ProfileUpdateForm extends ProfileForm
{
public function configure()
{
$this->useFields(array('email', 'other_field'));
}
}
I have a form object in jquery, and I'd like to select all inputs of this form.
Let's suppose my form object is called form. If the form has an id, I can just do
var id = form.attr('id');
var inputs = $('#' + id + ' input');
If not I can check this, and then manually add a temporary id, do the selection, and remove the id (or just leave it there). But this just looks too complicated, there must be an easier way, but I'm not able to find it.
Another possible way (which I'm not able to make work) would be something like
var inputs = $('input').filter(function() {
var parents = this.parents();
return ($.inArray(form, parents) != -1);
});
but this too seems complicated (and it doesn't work as stated).
By the way, from the performance point of view, which approach would be more convenient?
http://docs.jquery.com/Traversing/find
form.find('input')
should do the trick I would think. Just in case, if you're trying to get all of the input fields to grab their current values and submit them with AJAX you can just use the .serialize method of your form:
data: form.serialize(),
As far as your performance question goes, I believe your first method is more effecient, the second will iterate over every input on the page. As of jQuery 1.4 the first method is definitely more efficient, querying based off of object IDs initially has been significantly enhanced.
Im not sure what you are trying to do here... if there are multiple forms on the page then you have to have some kind of identitfier.. a pernt, and id, a class something. If you only have a single form then its as simple as $('form input').