Handling browser refresh with query filters from page parameters - google-app-maker

I have two data sources
Assets
Locations
Assets has a One to Many relation with Locations
Assets has a query builder data source, AssetLocFiltered, that is set with the following:
ParentLocationKey =:ParentLocationKey
ParentLocationKey is the relation field for the locations table.
On the home page you select a location and then click a button that passes the location ID to a parameter on the ShopPageDemo page. with the following code
app.pages.ShopPageDemo.properties.ParentLocationKey =
widget.datasource.item.Id;
console.log(widget.datasource.item.Id);
app.showPage(app.pages.ShopPageDemo);
One the ShopPageDemo Page there is a table view of the AssetLocFiltered that sets the query parameter in the ondataload event with the following code:
widget.root.datasource.query.parameters.ParentLocationKey =
widget.root.properties.ParentLocationKey;
widget.root.datasource.load();
This works great. The problem is when i hit the browser refresh it seems like it clears the property in ShopPageDemo. How do I handle this browser refresh issue? I am not really sure where to start.

There is more than one way to do this; However, the approach I usually take involves deep linking. In your case, you'll need to do something like this:
1.) On the button that takes you to the next page, add this code:
var params = {
key: widget.datasource.item.Id
};
var page = app.pages.ShopPageDemo;
app.showPage(page);
google.script.history.replace(null, params, page.name);
2.) On the ShopPageDemo onAttach event handler, add the following:
google.script.url.getLocation(function(location) {
widget.root.properties.ParentLocationKey = location.parameter.key;
var ds = widget.datasource;
ds.query.parameters.ParentLocationKey = widget.root.properties.ParentLocationKey;
ds.load();
});
For better performance, I would set the ShopPageDemo datasource to NOT load automatically and also to unload its data on the onDetach event handler like this: widget.datasource.unload().
Reference:
1. https://developers.google.com/apps-script/guides/html/reference/history
2. https://developers.google.com/apps-script/guides/html/reference/url

Related

Relational Query - 2 degrees away

I have three models:
Timesheets
Employee
Manager
I am looking for all timesheets that need to be approved by a manager (many timesheets per employee, one manager per employee).
I have tried creating datasources and prefetching both Employee and Employee.Manager, but I so far no success as of yet.
Is there a trick to this? Do I need to load the query and then do another load? Or create an intermediary datasource that holds both the Timesheet and Employee data or something else?
You can do it by applying a query filter to the datasource onDataLoad event or another event. For example, you could bind the value of a dropdown with Managers to:
#datasource.query.filters.Employee.Manager._equals
- assuming that the datasource of the widget is set to Timesheets.
If you are linking to the page from another page, you could also call a script instead of using a preset action. On the link click, invoke the script below, passing it the desired manager object from the linking page.
function loadPageTimesheets(manager){
app.showPage(app.pages.Timesheets);
app.pages.Timesheets.datasource.query.filters.Employee.Manager._equals = manager;
app.pages.Timesheets.datasource.load();
}
I would recommend to redesign your app a little bit to use full power of App Maker. You can go with Directory Model (Manager -> Employees) plus one table with data (Timesheets). In this case your timesheets query can look similar to this:
// Server side script
function getTimesheets(query) {
var managerEmail = query.parameters.ManagerEmail;
var dirQuery = app.models.Directory.newQuery();
dirQuery.filters.PrimaryEmail._equals = managerEmail;
dirQuery.prefetch.DirectReports._add();
var people = dirQuery.run();
if (people.length === 0) {
return [];
}
var manager = people[0];
// Subordinates lookup can look fancier if you need recursively
// include everybody down the hierarchy chart. In this case
// it also will make sense to update prefetch above to include
// reports of reports of reports...
var subortinatesEmails = manager.DirectReports.map(function(employee) {
return employee.PrimaryEmail;
});
var tsQuery = app.models.Timesheet.newQuery();
tsQuery.filters.EmployeeEmail._in = subortinatesEmails;
return tsQuery.run();
}

Wijimo Autocomplete & AngularJS - setting initial value from loaded data

I am trying to set the initial value in a Wijimo Autocomplete control which has been loaded from an external data source. The scenario being a form is used to create some new data and then is saved. Subsequently the data needs to be edited so it is reloaded into the form.
I can successfully use the Autocomplete on the initial form - the source list is a JSON Array of objects which is loaded into the controller. The app is using UI Router so I resolve this first.
When I save the data I serialise the selected Object from the Autocomplete control and is then saved to a Mongo DB store. When loading this data back in it is converted back to an object.
This is what the control looks like:
<wj-auto-complete
selected-index="selectedIndexCombo"
selected-item="selectedAirline"
items-source="airlineCodes"
display-member-path="Title"
placeholder="Airline Code"
max-items="50"/>
An example of the source list looks like this:
{
"#href":"\/airline.nsf\/api\/data\/collections\/name\/(LUAirlines)\/unid\/8DCD734E7BCDA24D80257C99003770C4",
"#link":
{
"rel":"document",
"href":"\/airline.nsf\/api\/data\/documents\/unid\/8DCD734E7BCDA24D80257C99003770C4"
},
"#entryid":"98-8DCD734E7BCDA24D80257C99003770C4",
"#unid":"8DCD734E7BCDA24D80257C99003770C4",
"#noteid":"FB2",
"#position":"98",
"#siblings":100,
"#form":"Airline",
"AirlineCode":"WN",
"Airline":"Southwest Airlines",
"Title":"WN - Southwest Airlines"
}
So when the form is initially created the controller property selectedAirline is correctly set with the selected Object.
So this works fine in the save function:
$scope.formData.selectedAirline = JSON.stringify($scope.selectedAirline);
But when reloading in the data:
AirlineInfoFactory.loadAirlineInfo($scope.reference).then(function success(response) {
$scope.selectedAirline = eval('(' + response.data.selectedAirline + ')');
$scope.information = response.data.information;
$scope.dataLoaded = true;
console.log($scope.selectedAirline)
$scope.selectedIndexCombo=11;
})
The autocomplete control does not bind to the selectedAirline property.
I tried using the selected-index attribute on the directive so see if I could just change it to something when the data loads but it doesnt work either. I suspect its to do with the digest loop but I am not sure.
Any ideas?
Thanks
I tried to replicate the scenario by reloading the data and setting the selectedAirline property and it works well withe latest version 32. Here is the fiddle:
http://jsfiddle.net/n1kpkcud/2/
` $scope.countries = initialList;
$scope.selectedAirline = '';
$scope.setItem = function () {
$scope.countries = reloading;
$scope.selectedAirline = 'Yemen';
}`
I would suggest you to update this fiddle so that it replicates the issue and I can suggest you accordingly.

Get shared pages using localized component

I'm currently working on a event handler, which will on save-event, save the latest revision date of the page and it's components into a custom database, and this is working, but i'm facing some performance issues.
Let me give you an example, for how it's working:
If a component is saved/updated (changes are made), then I want to update all pages using this component in my custom database.
Basic blueprint setup:
200 contains components
400 translation publication for components (inherent components from 200)
500 master publication for pages
600 local site publication inherent components from 400 and pages from 500)
So lets say we have component X in 200, this component is included in in a page in 500, X is localized in 400 (let us call it X(l)) and the page in 600 is NOT localized ( i.e it will use the component x(l))
So now to my question:
In my save event handler, i check what pages X(l) are included in , by using :
var filter = new UsingItemsFilter(component.Session)
{
IncludeLocalCopies = true,
ItemTypes = new[] { ItemType.Page }
};
but this will only give me references to pages from 500.
So what i then do (which feels kind of stupid) is to
create a tcm id of all pages in child publications(by looping over them) that inherent this page (now im using some psuedocodelike coding):
foreach(var 500page in foundPages)
foreach(var publication in publications){
if(subject.Session.IsExistingObject(
new TcmUri(page.Id.ItemId,page.Id.ItemType,publication.Id.ItemId)
))
{
someListThatWillContainAllChildPagesFrom500.Add(TheAboveTcmUri);
}
}
And then for each page, check the components in that page, and finally save this state to my custom database.
So the question is, is there a way by to query for all pages, that make use of the localized component, by using the TOM.NET api (no not CoreServiceClient)?
Is there a better way to find child publications of a publication, so I only need to check for pages in the childPublication?
Br Martin
The following code sample should give you the shared items of a specific local/localized item along with the item. BluePrintNodesFilter was introduced in 2013, however in earlier version BluePrintFilter should work in similar way.
SystemManager systemManager = session.SystemManager;
BluePrintNodesFilter filter = new BluePrintNodesFilter(session)
{
BaseColumns = ListBaseColumns.Id,
ForItem = page
};
IEnumerable<BluePrintNode> allNodes = systemManager.GetBluePrintNodes(filter);
IEnumerable<RepositoryLocalObject> sharedAndLocal = (from node in allNodes
where node.Item != null
where node.Item.OwningRepository.Id == page.OwningRepository.Id
select node.Item).ToArray();

Flash builder + Zend amf | Insertion function not working when called second time

I'm using standart createOrders function which is autogenerated by Flash Builder 4.6.
It works brilliantly when used once. Here is code:
protected function okButton_clickHandler():void
{
var orders2:Orders = new Orders();
//setting values
createOrdersResult.token = ordersService.createOrders(orders2);
ordersService.commit();
}
When same button is clicked second time and consequently okButton_clickHandler launched, data is not inserted to database.
I added result handler with trace("saved"); and what I saw was that "saved" was written on first click, but not second.
Also I used Charles to see whether request is being sent second time. And no it is not.
EDIT
Just tried to generate auto generate form. Only had to add commit(); because else request is not sent. And here is save problem — request is sent only on first button click.
EDIT 2
So all in all problem is in fact that ordersService.createOrders(orders2); works only once.
Because if i try
createOrdersResult.token = ordersService.createOrders(orders2);
ordersService.commit();
createOrdersResult.token = ordersService.createOrders(orders2);
ordersService.commit();
OR
createOrdersResult.token = ordersService.createOrders(orders2);
createOrdersResult.token = ordersService.createOrders(orders2);
ordersService.commit();
there is only one row added to database.
Any ideas?

jQuery UI autocomplete is not displaying results fetched via AJAX

I am trying to use the jQuery UI autocomplete feature in my web application. What I have set up is a page called SearchPreload.aspx. This page checks for a value (term) to come in along with another parameter. The page validates the values that are incoming, and then it pulls some data from the database and prints out a javascript array (ex: ["item1","item2"]) on the page. Code:
protected void Page_Load(object sender, EventArgs e)
{
string curVal;
string type ="";
if (Request.QueryString["term"] != null)
{
curVal = Request.QueryString["term"].ToString();
curVal = curVal.ToLower();
if (Request.QueryString["Type"] != null)
type = Request.QueryString["Type"].ToString();
SwitchType(type,curVal);
}
}
public string PreLoadStrings(List<string> PreLoadValues, string curVal)
{
StringBuilder sb = new StringBuilder();
if (PreLoadValues.Any())
{
sb.Append("[\"");
foreach (string str in PreLoadValues)
{
if (!string.IsNullOrEmpty(str))
{
if (str.ToLower().Contains(curVal))
sb.Append(str).Append("\",\"");
}
}
sb.Append("\"];");
Response.Write(sb.ToString());
return sb.ToString();
}
}
The db part is working fine and printing out the correct data on the screen of the page if I navigate to it via browser.
The jQuery ui autocomplete is written as follows:
$(".searchBox").autocomplete({
source: "SearchPreload.aspx?Type=rbChoice",
minLength: 1
});
Now if my understanding is correct, every time I type in the search box, it should act as a keypress and fire my source to limit the data correct? When I through a debug statement in SearchPreload.aspx code behind, it appears that the page is not being hit at all.
If I wrap the autocomplete function in a .keypress function, then I get into the search preload page but still I do not get any results. I just want to show the results under the search box just like the default functionality example on the jQuery website. What am I doing wrong?
autocomplete will NOT display suggestions if the JSON returned by the server is invalid. So copy the following URL (or the returned JSON data) and paste it on JSONLint. See if your JSON is valid.
http://yourwebsite.com/path/to/Searchpreload.aspx?Type=rbChoice&term=Something
PS: I do not see that you're calling the PreLoadStrings function. I hope this is normal.
A couple of things to check.
Make sure that the path to the page is correct. If you are at http://mysite.com/subfolder/PageWithAutoComplete.aspx, and your searchpreload.aspx page is in another directory such as http://mysite.com/anotherFolder/searchpreload.aspx the url that you are using as the source would be incorrect, it would need to be
source: "/anotherFolder/Searchpreload.aspx?Type=rbChoice"
One other thing that you could try is to make the method that you are calling a page method on the searchpreload.aspx page. Typically when working with javascript, I try to use page methods to handle ajax reqeusts and send back it's data. More on page methods can be found here: http://www.singingeels.com/Articles/Using_Page_Methods_in_ASPNET_AJAX.aspx
HTH.

Resources