Select options obtained via ajax and unmap issue - forms

I don't see any examples linking a form using select elements with options obtained via ajax. I am wanting to initialize a view model property via ajax in order to populate some select lists in my view and data-link the selected id from my model data. I don't need these arrays when doing an .unmap() of compiled view model because I don't want to send the large lists back to the server when updating the model. So, let's say I have data with ProjectID, ProjectDescription, ProjectTypeID, ProjectPriorityID. In my view model, I need to get via ajax a list of ProjectTypes and ProjectPriorities and use them in my view so that I can select the value from a list. I'm not sure how to achieve this without getting the lists as part of the data when doing .unmap() to send it back to the server.
If there is a property for "ProjectTypes" or "ProjectPriorites" in my view model, they always become part of the data when calling .unmap().
Thank you

There are different alternative approaches. One is to have a single model that includes both 'secondary data' - such as all the ProjectTypes - which will not change dynamically, and the 'primary data' which can get updated based on user input. In that case when you get plain JSON data back from the VM hierarchy using unmap() you can 'prune' it and send only the relevant 'primary' parts back the server.
Another approach is to keep the primary and secondary data separate - so the model is just the 'primary' data, and the secondary data is separate - for example, passed in as a helper:
// Instantiate View Models
var appVm = $.views.viewModels.MyModel.map(modelData);
var typesVm = $.views.viewModels.MyTypes.map(typeData);
$.templates("#appTemplate").link("#page", appVm, {types: typesVm});
<select data-link="typeId()"><
{^{for ~types.projectTypes()}}
<option value="{{:id()}}">{{:label()}}</option>
{{/for}}
</select>
You can also choose not to compile View Models for the secondary data, if it is basically 'static', and do:
$.templates("#appTemplate").link("#page", appVm, {types: typesData});
<select data-link="typeId()"><
{^{for ~types.projectTypes}}
<option value="{{:id}}">{{:label}}</option>
{{/for}}
</select>
Another approach is to only send back to the server any data values or array that have actually changed, for example by using a CRUD/REST web service approach server updates. In that case you would need to have code that diffs the data, or use observe or observeAll to respond to incremental changes...

Related

ExtJS - Add values to FormPanel when it's fully loaded, including select stores

In ExtJS modern 6.2, I want to set the FormPanel values using form.setValues(), but the stores of select fields are not loaded yet.
How can I execute the form.setValues() only when the form is 100% loaded?
FormPanel has a "painted" event. You could set the values from this event.
I don't generally use the setValues(). My data is stored in both Stores and Models. Then I just bind the values in the form to the values in the Model. Then when the form is ready it will display the values. As the users edits the fields the data in the model is updated (two way binding). Then after the form is validated you can call save on the model (or sync on a store).

SelectDialog Only returns the first 20 items

I have this Fragment:
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m">
<SelectDialog title="{i18n>titreVoiture}" search="ChercherVoiture"
confirm="fermerdialog"
cancel="fermerdialog" items="{VoitureModel>/GrosVoitures}">
<StandardListItem title="{VoitureModel>NomVoiture}" type="Active"/>
</SelectDialog>
</core:FragmentDefinition>
I am handling the selection of items. I put the selected items in an array and then when I click to open the dialog, I loop on the items and set the items manually with setSelected() if it exists in the array the problem is when I want to retrieve the items using this._valueHelpDialog.getItems().
It only returns the first 20 items, and I checked the modal and in the list it displays all the items, so I wonder why getitems() doesn't return all items.
If your entity set in gateway have 1 million records, UI5 will not lot all of them - assuming you are using an oData Model.
When your model is an ODataModel, lists by default consume the entity sets using query parameters $top and $skip. Also, by default Lists get records by blocks of 20.
As you called method "getItems" - you are getting the items in your list, not data from your model.
It's possible to use the method read of class ODataModel to read your entity set without binding it to a control however I believe reading a pottentially large data set inside you app is not ideal.
If would be helpful to share what you are trying to achieve apart from sharing your code.

How to see few fields in the view but later clicking on the record should show all fields?

My HANA table consists of 20 fields but I want my view to display only 5 fields for each record in my browser through an xml view. But again, when I click on the particular row on browser, I should be able to see all 20 field for that record. How will that be possible?
That's the classic master detail pattern, and can be solved quite nicely.
In your master view, you can set the binding of your table to the OData entity set as per usual, but to limit the number of fields being transferred, you should use the select parameter:
items="{
path: '/AwesomeStuff',
parameters: {
select: 'Id,Name'
}
}"
The press event of your ColumnListItem in the table should be implemented and in that event handler it would be nicest to use the router and navigate to e.g. path /AwesomeStuff/12345.
In your detail view, you'll have to create a handler that responds to something that happens in the master, e.g. navigation. You could do this by binding an event handler to the router in the detail view, e.g.:
this.getRouter().getRoute("AwesomeStuff").attachMatched(this.onRouteMatched, this);
In the implementation of the onRouteMatched handler, bind the detail view to the full set of record data by:
this.getView().bindElement({
path: this.getModel().createKey(
"/AwesomeStuff",
{ Id: oEvent.getParameter("arguments").Id })
}});
The bindElement method binds the (detail) view to a single OData element (not a list). If this element is cached in the ODataModel, it will be re-used. But if it's not in cache, a request is made to the server. Note that you can leave the select parameter away from this call, as you want the full set of data in your detail view, which is the default.
If you're looking for some code samples, generate a new project from the "SAP Fiori Master-Detail Application" template in SAP WebIDE.

InfoPath 2010: Mirror data from a Secondary Data Source

Goal: Pull data from a SharePoint 2010 List using a WEB ENABLED form. Then, from the repeating table that contains the secondary data, extract only the desired data and mirror it in my main form fields. The extracted data would then be modified, and submitted to another sharepoint list using Nintex Workflows or, if the IT department smiles upon this project, a database.
What I've Tried: Created a field, named "TEST_CyS", in a repeating group, named "TEST", in my main form fields to store the mirrored data. This field has a default value of:
xdXDocument:GetDOM("REMOVED")/dfs:myFields/dfs:dataFields/d:SharePointListItem_RW[(count(../preceding-sibling::*[local-name() = "TEST"]) + 1)]/d:Cy_Statement
This is refreshed when the form updates.
If I set the default value to count(../preceding-sibling::*[local-name() = "TEST"]) + 1 it accurately counts each inserted group.
if I set the default value to xdXDocument:GetDOM("REMOVED")/dfs:myFields/dfs:dataFields/d:SharePointListItem_RW[<INT>])]/d:Cy_Statement where <INT> is any whole value between 1 and n then the field will display the correct information, for the secondary data field whose index is referenced.
It's when I combine the two that things fall apart.
Main Data Tree:
Secondary Data Tree:
Assumptions: I am guessing that the preceding-sibling::*[local-name() = "TEST"] axis is not returning a value due to the fact that it's being called along with the GetDOM() method. I've tried to point the preceding-sibling back to the correct group in the Main form fields, but then I felt silly for trying that as it wouldn't know where to start counting AND infopath presented me with an error:
Function 'GetDOM' did not return a value, or it returned a value that cannot be converted to an XSL data type.
Summary: Is this a lost cause without code or purchasing some "plugin" for Infopath like qRules? The IT department will not budge on allowing Forms with code in them to be run on the SharePoint site, and the requirements placed on the form state that it must be a web enabled form to be filled out in SharePoint.
Edit: We also do not have access to VSTA, and the possibility of having it installed is very, very slim.
Is there an alternative method I could use to pull this off?
SharePoint admins don't need to be involved if the InfoPath form uses code, so long as it is limited to the SharePoint 2010 sandbox APIs.

How to work with select input with data coming from a simple relational db model

I'm using Angularjs plugged into a API which retrieves data from a mysqlk normal relational db.
Let's say I have this simple data model in my bdd:
table car:
id,
type_id
table type:
id,
label
I have a API which retrieves the data from DB to have the list of cars and the static labels from db:
http://myapi/car/
response :
{[{id:1, type_id:2}, {id:2, type_id:3}]}
http://myapi/carstaticlabel/
response :
{[{id:1, label:convertible}, {id:2, label:limousine}, {id:3, label:pickup}]}
My aim is first to display a list of cars with the type label and then, open a dialog and being able to show a form with preloaded values of the selected car:
rendered list of cars :
1 convertible
2 pickup
rendered form for edited car whose id is 1:
select the type of car:
<select>
<option value="1">convertible</option>
<option value="2" selected="selected">limousine</option>
<option value="3">pickup</option>
</select>
I have tried different approaches but none is elegant
Solution 1
for the list of cars
change my API and make the join directly between car and type to get the list with label:
http://myapi/car/
response :
{[{id:1, type_id:2, type:{[id:2, label:limousine]}}, {id:2, type_id:3, type:{[id:3, label:pickup]}}]}
then I just assign in the form : car.id and car['type']['label']
ISSUE: each car will contain repeated information (label) >> bloated info
for the edit form:
I pass the json of selected car to the form and set default values:
<p>type: <select ng-model="car.type" ng-options="type.label for type in type_list" required></select></p>
MY ISSUE with that:
when I submit the form, I don't get the type_id directly, I get the car.type object instead, so I need to painfully translate it into an id to post into the database.
To convert I have to go into the car.type object and retrieve the object inside and then retrieve its id... very unelegant.
Solution 2
make the "join" inside angular by working with arrays.
ISSUE: very hard to default values in the form later on
I'm lost, what is usually the best practice to achieve that simple task?
You should use select as label for value in array syntax for array data sources. Your example have complex data structure which is array of objects. So you need something like this:
<select ng-model="selectedId"
ng-options="x.id as x.label for x in response">
</select>
I created little example here to demonstrate proposed solution.