I have a list of AccessPrivileges and I would need to create a form with a dynamic list of checkboxes, however I cannot find a solution inside the documentation.
Assuming you have the following
class AccessPrivilege(dataType:String, description:String)
object AccessPrivilege {
val privileges:Seq[AccessPrivilege] = ....
}
I would need to generate a binding so that , in my form I can:
Have a checkbox whose label is the description
Being able to retrieve the list of selected checkboxes as a List of String and not as a List of boolean.
I can't find among the form helpers what I need, because the checked returns a boolean, while I need to "collect" the selected checkboxes...
Related
I have a form with a set of questions, and I want to use it for other forms creation. In other words, I want to iterate through this template form items, choose those that I need and append them to another, newly created form.
I had no problem with getting the items and choosing those that I need; however, I can't find the way to append these items to another form - all of the Form.addSomethingItem() methods don't take arguments (docs for example). Is it really impossible, or do I miss something foolishly simple?
There are two ways to achieve this:
Make a copy of the form using DriveApp and remove/modify items in-place on the new form copy.
Iterate over existing items, check it's type and add them to the new form. For example, The following gets Item1's enum and converts it to a camelCase string and executes add{Type}Item method, where Type is MultipleChoice in case of MULTIPLE_CHOICE Enum Item type.
const newForm2Item0 = Form2[
`add${String(Form1.getItems()[0].getType())
.toLowerCase()
.replace(/(^|_)[A-Z]/gi, match =>
match.toUpperCase().replace('_', '')
)}Item`
]();//equivalent to Form2.addMultipleChoiceItem()
You would then add choices and other configurations as needed in a similar manner.
Form methods like addTextItem() don't take arguments, rather they return Items classes (e.g. TextItem). Those Item classes have their own methods for assigning properties to a question on a form.
Examples
here's an example of adding a text item with a specific title
form.addTextItem().setTitle('I am a text question title');
here's an example of adding a multiple choice item to a form with some choices
var item = form.addMultipleChoiceItem();
var choices = ['choice 1', 'choice 2', 'choice 3'];
choices.forEach(function(choice) {
item.createChoice(choice);
})
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.
I know I can get a binding associated with a control via control.getBinding('example').
Is there anyway to go the opposite way like binding.getControl()?
Not sure if this helps, but take a look at the control property "fieldGroupIds". It's used for validation purposes so you can call all the controls linked to that specific field group. You could use this to identify all the controls using that specific binding and calling all the controls linked to that field group. See documentation below:
Field Groups
Accessing Controls in a Field Group:
In some scenarios, it is required to find all controls that belong to a specific field group, or to all controls with a fieldGroupId. For this, the control implements the public getControlsByFieldGroupId method that gets a list of child controls in the application code.
var aAllControlsWithFieldGroupId = myVerticalLayout.getControlsByFieldGroupId(); //all where fieldGroupId is not empty
var aMyGroupControls = myVerticalLayout.getControlsByFieldGroupId("myGroup"); //exact matches to myGroup
Similar to the above you can use the byFieldGroupId method of sap.ui.Core to all controls with certain field group IDs.
var aAllControlsWithFieldGroupId = sap.ui.getCore().byFieldGroupId(); //all where fieldGroupId is not empty
var aMyGroupControls = sap.ui.getCore().byFieldGroupId("MyGroup"); //exact matches to myGroup
var aNotGrouped = sap.ui.getCore().byFieldGroupId([]); //exact empty array (default value of fieldGroupIds)
This is the List Report type of Smart Template application
Here I have selected 2nd and 5th row, I also have a button named Send Requests in the section part which is highlighted. If I click this button it calls a javascript controller function which is defined in the extensions of the application. In this js function how can I retrieve the selected rows that are selected?
I have enabled the checkboxes in this page by mentioning this code
"settings": { "gridTable": false, "multiSelect": true } in the manifest.json
As it was recommended by this link https://sapui5.netweaver.ondemand.com/#docs/guide/116b5d82e8c545e2a56e1b51b8b0a9bd.html
I want to know how can I retrieve the rows which got selected?
There is an API that you can use for your use case. It is described here: https://sapui5.netweaver.ondemand.com/#docs/guide/bd2994b69ef542998becbc69ab093f7e.html
Basically, you just need to call the getSelectedContexts method. Unfortunately you will not be able to really get the items themselves, only the binding contexts (which point to the data entities which are selected). Excerpt from the documentation:
After you have defined a view extension, you can access and modify the
properties of all UI elements defined within these extensions (for
example, change the visibility). However, you cannot access any UI
elements that are not defined within your view extensions.
In this type of table there is way.
var myTable=sap.ui.getCore().byId("your table id");
get all rows:
var myTableRows=myTable.getRows();
now get selected Indices
var selectedIndeices=myTable.getSelectedIndices(); //this will give you array of indeices.
now run loop on indeices array. And get particular row item;
// get binding path
var bindingpath=myTableRows[2].getBindingContext().sPath; // this will return eg:"/ProductCollection/2"
// now get Binding object of that particular row.
var myData=myTableRows[2].getModel().getObject(bindingpath); // this will return binding object at that perticular row.
// once your loop is over in the end you will have all object of selected row. then do whatever you want to do.
If you use smart template create an extension.
This is the standard event befor the table is rebinding:
onBeforeRebindTableExtension: function (oEvent) {
this._table = oEvent.getSource().getTable();
}
In your action function (or where you want) call the table and get the context :
this._table.getSelectedContexts();
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();