Select all Rows in Dynamics CRM Grid - grid

Lets say I have a Grid in CRM showing me Invoices which need to be created by using a custom javascript dialog. In this dialog I want to put two options which are doing the following:
1) selects all Rows flagged as selected in the Grid
2) selects all existing Rows in the Grid
Particularly I have an issue with No. 2)
I cannot figure out how to get all rows if I have lets say 5 pages of invoices. So how can I select all rows in the Grid and not only those shown on the actual grid page?
Any advice is highly appreciated.
Regards
Sandro

If you want to retrieve only the elements that are selected in a grid, then you can use the Ribbon Workbench to configure a new button on the sub grid. The Button must have a Command Action which can be configured to pass selected items to a JavaScript method using the SelectedControlSelectedItemIds parameter
There is a SelectedControlAllItemIds parameter too, but I think this only gives "All Items" in the current page, not all pages. Not sure about these last bits so definitely worth a try
If that doesn't work, then you will have to do this yourself using a WebApi call. For example, to get all Contacts associated with an Account, you might do something like this:
// Get the ID of the parent account
var accountid = {AccountId};
// Execute a query to retrieve all Contacts associated with the given Account ID
Xrm.WebApi.retrieveMultipleRecords("contacts", "?$select=contactid&$filter=_parentcustomerid_value eq " + accountid)
.then(
function(results) { console.log(results); },
function(error) { console.log(error); }
);
Read more about retrieveMultipleRecords here

Related

GSuite Appmaker - how to set default value in table using button

I am trying to put together a mock up for a data collection app for a local nonprofit using GSuite's AppMaker. So far I really like the tool.
One thing I need to be able to do is streamline the data entry for the site representatives. In my app, I display a list of students in a table, where one of the columns is a boolean value which represents attendance. The desired result is for the teachers to be able to input the date field one time using the date input button at the bottom of the page. Then they can quickly point and click down the Present column to log attendance.
My question is: how would I link the date selector dropdown so that the date field pre-populates with the selected date from the input field? I don't want them to have to enter the field over an over again since its the same for each row and I don't want the user experience to feel clunky.
Screenshot of the App for reference:
Using client script, you can add the following to the onValueEdit event handler of the date widget at the bottom.
var items = widget.root.descendants.<YourTable>.datasource.items;
items.forEach(function(item){
item.<DateField> = newValue;
});
The only thing to take into account is that when using client scripting, you will only update the records loaded in the table at the moment; i.e, if your table has paging, it will only update the current page. If you are using paging, then you will need to add the following code to the onPreviousClick and the onNextClick event handlers of the pager widget:
var selectedDate = widget.root.descendants.<YourDatePicker>.value;
var items = widget.root.descendants.<YourTable>.datasource.items;
items.forEach(function(item){
item.<DateField> = selectedDate;
});

In App Maker, how do you make dynamic table cell text?

In App Maker, I am displaying a table and want to replace table cell data with different text using a data lookup from another table. Assume two tables, Departments and Employees.
Departments is two fields, DeptID and DeptDescription.
Employees is multiple fields including DeptID.
In the table listing for Employees, I would like to replace the DeptID with the DeptDescription. (The page datasource is Employees. I do not want to set up a relationship between the data models.)
I am guessing I want to do some scripting in the onDataLoad event for the table cell label for DeptID. I have this much so far:
app.datasources.Departments.query.filters.DeptID._equals = widget.datasource.item.DeptID;
app.datasources.Departments.newQuery().run();
widget.text = app.datasources.Departments.item.DeptDescription;
I know this is not correct, but am I close?
This answer is untested, but I wanted to present a possible solution that would not require a lot of DB calls, especially ones that make repeated calls to a server script which might consume a lot of processing time when you do line item calls.
Set up a separate datasource under the Department model. Change the default 'Query Builder' to 'Query Script' and add a parameter of type 'list(number)' or 'list(string)', this should match your Primary Key field type. Uncheck the 'auto load' option.
In your 'Query Script' portion enter the following code:
query.filters.Id._in = query.parameters.YourParameter;
return query.run();
Go to your Employees datasource that is supposed to generate your table and find your 'On Load' client script section. In this section enter the following code:
var departmentsDs = app.datasources.YourDepartmentsDs;
departmentsDs.properties.YourParameter = datasource.items.map(function(deptIds) {return deptIds.DeptID;});
departmentDs.load();
Now go the page that contains your table. If you have not already create a label widget do so now. In this label widget for the text binding enter the following:
#datasources.YourDepartmentsDs.loaded && (#datasources.YourDepartmentsDs.items).map(function(Id){return Id.Id}).indexOf(#widget.datasource.item.DeptID) !== -1 ? #datasources.YourDepartmentDs.items[(#datasources.YourDepartmentsDs.items).map(function(Id){return Id.Id}).indexOf(#widget.datasource.item.DeptID)].DeptDescription : 'Unable to retrieve Dept Description'
As stated this is untested and I wrote the code from memory without App Maker in front of me so it may require some additional tweaking. Going with the first option presented by J.G. would also be a very viable solution though. And I apologize but the code formatter does not seem to be working for me.
1 way) Create an aggregate table that joins your tables if you need to bypass using the relations feature. This way you can use sql to join the two tables in the datasource definition
2) if you don't want to make a new table. Change the text from a value binding to "more options"
=getDescription(#datasource.item.DeptId)
and then the code you wrote in a client side script
function getDescription(id){
google.script.run
.withSuccessHandler(function successHandler(result){ return result;})
.withFailureHandler( function failureHandler(e){ console.log(" Failed" +e);})
.queryValue(id);
}
server side script:
function queryValue(id){
var query = app.models.Departments.newQuery();
query.filters.DeptID._equals = id;
var results = query.run();
return results[0]["DeptDescription"];
}
that last line might be results[0].DeptDescription

Google App Maker not reocognising some of its own widgets

In Google App Maker, I have several widgets on a page.
One of these widgets is called Label12 (shown in Screenshot 1).
It definitely exists and is also shown in the breadcrumb trail at the top of my screen.
However, when I attempt to reference Label12 in my code, it does not seem to exist.
If I use the ctrl+space code completion helper, the Label12 widget is not shown as an option (shown in screenshot 2).
When I attempt to code it manually (e.g. app.pages.Reconciliation_Details.descendants.Label12.visible) it returns the error "Cannot set property 'visible' of undefined".
Why can App Maker not see Label12?
Screenshot 1 showing Label12 on page:
Screenshot 2 showing absence of Label12 when coding:
App Maker can see Label12. The point is that the label is inside a table widget, hence according to the documentation:
Because a table is a collection of other widgets, you can't use the Widget API to interact with a table. However, you can use scripts to manipulate the individual widgets that make up a table.
The above statement makes sense because the amount of rows a table will display depends on the datasource items; i.e., the rows are dynamically created when the widget datasource is loaded in the ui. Therefore, in order to access the label you need to first access the children of the Table1Body, which is a collection of named values known as PropertyMap.
I believe you are trying to hide/show that specific label based on some logic. The correct way of doing it would be something like this:
var rows = app.pages.Reconciliation_Details.descendants.Table1Body.children._values;
for(var i=0; i<rows.length; i++){
var row = rows[i];
var label = row.descendants.Label12;
label.visible = true; // or false
}

Suitescript Matrix Item cant get record ID

im testing out an after submit event on a matrix item.
I can see in my logs its reporting as an inventory item, however there is no internal ID unlike all the other records I have tested this against.
function afterSubmit(type)
{
var recType = nlapiGetRecordType();
var recId = nlapiGetRecordId();
dLog('matrix id',recId);
}
recId is always blank....
dLog() is a function we use to make it easier to log to the netsuite log files
I see nothing wrong. I tried that on a matrix item myself and worked fine. I suggest checking dLog or using normal debug statements.
It will not give record id on aftersubmt.. because items are created after the click of 'create matrix items'. Matrix items does not support aftersubmit event. If want to do scripting on matrix items, you have to write a scheduled script.

Processing variable number of form fields

I am working on a form which displays information about orders. Each order has a unique id, but they are not necessarily sequential on the form. Also, the number of fields can vary (one field per row on the form). The input into the form will not be mapped straight into the database, but will be added to the current value in the database, and then saved. An example of the form is in the picture below - the callout on the right shows the id for each row.
I know how to generate the form like this, but I can't work out how I can easily process each of these rows reliably. I also know how to give each of the fields a unique identifier, like name="order-23" or name="order[23]", but how can I translate that name so that I can update the related record in the database?
EDIT: One solution I can think of would be to iterate through every form field in the FormCollection, and if the name of the field matches the pattern, then I will extract the number from that field-name and process it.
However, I feel that there must be a much easier way to go about it - this method would likely involve a fair bit of string processing on each field, and there would possibly fall over if I have to add extra fields for each row later on.
Don't you have a list of IDs after postback? I believe you should not depend on what IDs are actually sent from the form, as anybody could change the IDs on the form to whatever they want, so it's a security issue. So you should after postback have a list of IDs you want to update (the same list you used to create the form with). In that case, you know exactly what id string you should use to retrieve the value from FormCollection.
In case you really can't get the list of IDs you are going to update, just use the FormCollection iteration as you suggested in your comment. The string processing is not that expensive in comparation with all other stuff being done at request processing.
If you have the names, then simply read the values by using Request.Form["order-23"] or re-create the controls in page pre-init and you'll have access to the values in your save event directly through the created controls.
I've done this loads in my CMS.
Essentially i sort of cheated.
The idea is something like this ....
render the form to the client, then look at the source code gneerated.
You should see that it generated a form tag with an action attribute.
When you click the submit button the form will be sent to that url so in the case of an order submission you would post the page back to OrderPage.aspx?OrderId=xxxx
then on the server you would build an update statement for your db that contained something like ...
"Update orders where order id =" + request.querystring["OrderId"]
So how do you update the action ...
In the calling page lets say you have a link called "New Order", when that link is clicked you need to do 2 things ...
redirect to this page.
generate an order id for this new order.
ok the first is simple, simply link it to this page.
the second ...
if this page is not a postback if(!IsPostback) { /* get a new id */ } depending on your order id's this may involve generating a new guid or doing something like getting the next number in a list by doing a select max(id) from a db.
once you have this new id you should still be in the page_load event.
this.form.Action = this.form.Action + "?OrderId=" + yourNewOrderId;
... tada ...
Send page back to the client.
view the source.

Resources