SAPUI5: How to create a control hierarchy? - sapui5

I hope you can help me with this. After reading all the documentation several times, googling for days, etc I don't find the way to do what i'm going to explain in a clean way, and in think I'm missing something because it's a really basic scenario.
I'm working with oData models, in this case 2 named models, "Model1", "Model2". Now what I want is to show a "parent" ComboBox based on an oData path, and a table that changes its items depending on the selection, in other words.
Model1 { //JSON representation of the data.
Accounts:[
"account 1": {invoices: ["invoice1", "invoice2", "invoice3"]},
"account 2": {invoices:["invoice4", "invoice5"]}
]
}
Combo Box:
<... items={Model1>/Accounts} /> -- This works and shows Account 1, and Account2.
Table
<Table... items="{Model1>Invoices}">
..
<items>
....
</items>
</Table>
What I want is the table to change it's context to the account selected on the ComboBox. The point is that this works, but the first time it loads the view, as there is no account selected, it calls the wrong odata path MYSERVICE/Invoices, instead of doing nothing, as the Account is not set yet, and the path for the invoices, once selected the account, shoud be MYSERVICE/Account('Account1')/Invoices for example.
I know I can achieve this with code, but I'm sure there must be a clean way to do this.
Seriously, this is driving me crazy.
Thanks for your help.

Are you sure that
items="{Model1>Invoices}"
triggers odata call? Because this is a relative path (without leading slash), normally it should not do the call.
What you can do:
Handle ComboBox selectionChange event;
In this event handler, create a path that you will bound the table to. In your case the path could look like this: "/Account(Account1)" - "/{EntitySetName}({KEY})". You can make use of createKey method of ODataModel2;
Set the table's context using the path:
oTable.bindObject({
path: sPath,
model: "Model1",
parameters: {
$expand: "Invoices"
}
});
Once the context is set, the relative binding will start working automatically and table will get the "Invoices"
I assume that the Account and Invoices are linked via navigation property and one-to-many cardinality, that's why the $expand parameter will load the corresponding invoices.

Related

How to make a custom ListView page in SuiteCRM

I need to make a page in SuiteCRM (v7.9 -- based loosely on Sugar 6.5 CE) that has a list of objects (of a custom module), with checkboxes in front of each one. So far, so good: that's a standard ListView.
The catch is that only some records should be in the list (filtering on whether there is an associated row in a related custom module/object).
This page needs to be distinct from the "regular" list for this module, which should indeed list all records.
It seems to me it makes sense to use a custom "action" to access this page view, and I can get my custom action code to fire with the right URL.
But I don't see how to hook in the filtering. At first, it looked like the process_record logic hook might be helpful here, but it just gives the bean for every record to be displayed. Unless there's a flag "display this record" that I'm not seeing, that's not so helpful.
Ideally, of course, I'd like to be able to inject a different WHERE clause in my custom controller action before calling
parent::action_listview();
to display the page, but I'm not seeing doc to indicate how that might work. I would include source code, but so far, the line above is everything (but boilerplate) that's in the controller.php file.
Create a copy of listview in custom folder and then override the listview's listViewProcess() method and insert your query there:
function listViewProcess() // generating listview
{
$this->processSearchForm();
if($this->where==''){
$this->where.="leads.status='Converted'";
}
$this->lv->searchColumns = $this->searchForm->searchColumns;
if(!$this->headers)
return;
$this->lv->setup($this->seed, 'custom/modules/Leads/ListView/ListViewGeneric.tpl', $this->where, $this->params);
echo $this->lv->display();
}
More info: http://wiki-crm-forum.com/forum/viewtopic.php?f=2&t=9420&p=32674&hilit=listViewProcess&sid=21907ecd28734a726f61f7017a7e9a24#p32674
Another tested working example can be found here:
How to hard code the where condition in list view ,basic search,advance search in sugar CE
P.S: I'm not so sure about "v7.9 -- based loosely on Sugar 6.5 CE" I'd say it's 95% identical apart from API stuff
for custom modules in SuiteCRM.
You may change in function create_new_list_query.

How to dynamically change dialog with select field

I'm new to Magnolia, and I'm making my own module.
I have a dialog box when adding a component and I want to change next fields below dynamically using a select field.
Example:
Select field with {"type 1", "type 2", ...}
IF "type 1" is selected
->show a text field below
ELSE
->show a basicUpload field below
Thanks in advance.
I believe same was already discussed here and few other places if you look over questions tagged "magnolia".
Long story short, fields are atomic, independent entities. They do not know about each other. So the only way to create such dynamic connection is over "parent" form. You need to extend form presenter and field factory (if you want select that would be SelectFieldFactory) and in there, when field is created, attach value changed or similar listener to it so when value is changed in the field, you can inform presenter to make some other field visible or hide it.
IIRC you can see example of that done in External Forms module (if you have access to enterprise code). Not sure if any of the community modules show the same.

Lightswitch HTML Client, Set Default Value of List Picker

Lightswitch renders my navigation property as a list picker, but I can't figure out how to set a default value on it. There must be a simple way to do it. I've scoured the net, and all the suggestions look hopelessly kludgy. Is there a good comprehensive tutorial out there for Lightswitch? The most common tasks like setting the default value on a dropdown are ridiculously hard to figure out.
Here's how I did it.
myapp.Address.created = function (entity) {
myapp.activeDataWorkspace.MailListData.CountryRegion_LUs.filter("CountryRegionCode eq 'US'").execute().then(function (result) {
entity.CountryRegion_LU = result.results[0];
});
}
You want to write a handler for the created Javascript event for the parent entity. I'm binding CountryRegion_LUs, which are in the Address entity, so I am binding to the created event of the Address entity, not the CountryRegion_LUs entity. "MailListData" is the name of my database. I'm using an OData query to pull out the CountryRegion_LU that has a CountryRegionCode of "US." I could have simply used "load()" instead of .filter("CountryRegionCode eq 'US'").execute() to load all the records, and then picked the member of the result-set I wanted, say results.result[221], but then I'd be bringing all the data over and filtering client-side.
refer to this post of which I asked myself, there is a detailed answer on the problem you have above: it explains how to set your modal picker/details picker with a default value
Lightswitch HTML Client - set modal picker value when screen created
any questions feel free to ask

ExtJS 4 - How to load grid store with its params carrying latest values from a form?

I have a window with a search form at the top and grid at the bottom.
User can enter values in the search form and click button - Get Records.
At the click of this button, I load the store of the grid by passing the values in form fields as parameters in following way:
store.load({
params:{
key1:Ext.getCmp('field1').getValue();
}
});
I tried giving parameters in the store proxy itself, but it unfortunately always takes up initial values (values when the form is rendered) and not the latest one entered by the users in the form fields. Following is the method I used for assigning values to params while creating the store:
extraParams:{
key1:Ext.getCmp('field1').getValue();
}
I wanted to seek guidance at two things:
a. While defining a store, can I ensure that store takes latest/current values from the form fields before querying server, so that I don't have to provide these values while calling load function?
This becomes more necessary as I have a paging toolbar at the bottom which carries a refresh button (along with next, last, previous, first icons for navigation).
Now, whenever user clicks at refresh (or any navigation icon), the store gets loaded without the query parameters.
Thus the second thing is:
b. If the answer of 'a' is that - Pass the latest values to parameters manually when calling load function - then how can I write the handler for 'refresh' button and navigation icons (that is, next, last, previous and first) in the paging toolbar, so that I can pass the latest form values to load function.
Thanks for any help in advance.
PS: I am using ExtJS 4.
yourStore.on('beforeload',function(store, operation,eOpts){
operation.params={
status:cmbStatus.getValue(),
value:txtBuscarPor.getValue(),
empresa:'saasd',
app:'dsads'
};
},this);
Related to your question (b) (and because you especially asked for this in the comments section):
I see only one standard way to hook into the PagingToolbar button handlers which is very limited.
Ext.toolbar.Paging fires a 'beforechange' event before it actually changes the current page. See API docs. A listener that returns false will stop the page change.
All other methods require extending Ext classes which wouldn't be a problem if the ComboBox would make it easier to use your own implementation of BoundList (which is the class that renders the dropdown) or pass through config parameters to BoundList resp. the paging toolbar.
I tried to bring this lack of flexibility up on the Ext message board once but was pretty much ignored.
A possible solution for this is to use 'beforeload' event of the store and provide the list of parameters in it. This way, whenever the store is loaded, then its beforeload event is fired and the values picked up are always the latest. Hope this helps someone looking for something similar.

cakePHP: automagic form elements, populating selection list

I have two tables, users{name,id,age_range_id} and age_ranges{id,range_name}.
There are also two models, controllers and the proper view files.
In the views I have the adduser.ctp file, which hold the proper form.
What I want is to have an input (select) that will hold the options from age_ranges.name field.
So, in the users model I've added var $hasMany = 'age_ranges';
What's next?
I know that I can use the $this->set to store the options as an array in the controller and then use it in the view.
but I assume(wrongly?) that by relating the models there is an 'automatic' way to do it.
Which lead me to the question: how?
I won't repeat what Thorpe and dogmatic have already written. They are both correct.
However, although it's difficult to be sure without seeing your model files, commonsense tells me that in the User model the relationship should be User:hasOne:AgeRange and in the AgeRange model it is AgeRange:hasMany:User, not the other way round as you have written.
Also, you do not specify the table name ('age_ranges') in the relationship, but the Model name ('AgeRange').
See these pages in the manual:
http://book.cakephp.org/view/1001/Understanding-Models & http://book.cakephp.org/view/1039/Associations-Linking-Models-Together
add $this->set('ageRanges', $this->User->AgeRange->find('list')); to the controller action
then add $this->Form->input('age_range_id') to the form
You can do this:
$this->User->AgeRange->find('list') and pass that to the view for a select statement