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.
Related
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
I created this sample locally
http://demos.telerik.com/kendo-ui/mvvm/remote-binding
In my 'update' transport, I did modify the 'ProductName' from my WebAPI
public IHttpActionResult Update(Product prod)
{
prod.Price = prod.UnitPrice * prod.Quantity;
prod.ProductName = prod.ProductName + DateTime.Now.ToString();
return Ok(prod);
}
It did update and reflect on my 'dropdownlist'.
The issue is the textbox id=products is not showing the latest productname. The textbox is binded using
data-bind="value: selectedProduct.ProductName"
How can I refresh this text box ?
Thank you.
All is same except this
update: {
url: "/Product/Update",
contentType: "application/json",
type: "POST"
},
and this.
parameterMap: function (data, type) {
return kendo.stringify(data);
}
If these changes are not made; my webapi will not receive any value.
I notice like the binding somehow got broken momentarily; is it because its indirectly reference using the var 'selectedProduct' ?
The reason, I believe, that your textbox is not updating is because of two reasons: 1) you're changing the data on the server instead of the client, and 2) the textbox is tied to the selectedProduct variable which is in no way tied to the data source.
In other words, when you submit the update, because your dropdown list is bound to the productSource data source, it's data gets updated automatically and the list is refreshed to show you the changes. This is expected. On the other hand, selectedProduct is not tied to the data source in any way, so, it still holds the old value before the update was called.
The solution is you have to manually update selectedProduct after the update request returns.
From time to time I have the requirement to bind a control property to based on data out of model A to another model B.
For example the syntax could look like this (but will not work):
text : "{B>/rootB/{A>someValue}/propertyB}"
I normally solve this problem by "misusing" an unused control property in combination with the format function. It would look like this:
tooltip : {
path : "A>someValue",
formatter : function(oValue) {
// do some checks on oValue
var path = "B>/rootB/"+oValue+"/propertyB";
this.bindProperty("text", path);
return undefined; // because tooltip is not used
}
The benefit of this, each time "A>someValue" will be changed the binding of "text" will be updated automatically.
It is also possible to do this in template code (like items aggregations).
But you may smell the code ;)
Any suggestions to make it cleaner?
As far as I know, there is no such possibility in UI5 (yet). I always use a formatter function as you already mentioned. I say not YET, because developers seem to be aware of this feature request: see on GitHub
BUT, you dont need to missuse a random control property! Just use the formatter to read the needed values from any model you have access to:
text : {
path : "A>someValue1",
formatter : function(oValue) {
// read model B to get someValue2 (based on someValue1)
var path = "B>/rootB/"+oValue+"/propertyB";
var B = getModel("someModel");
var someValue2 = B.getProperty(path);
return someValue2
}
I want to implement a serverside download process which reports its progress to the client.
I defined a global variable in my .aspx site class:
Public progressStatus As Integer
Then a start a new Thread to download the images in a List, which also changes the value of the global variable:
For Each imageUrl In imageFiles
currentUrlCount = currentUrlCount + 1
indexOfUrlSplit = imageUrl.LastIndexOf("/")
localFilename = imageUrl.Substring(indexOfUrlSplit + 1)
If localFilename <> "" Then
httpClient.DownloadFile(url, localImage)
progressStatus = CInt((currentUrlCount / totalUrlCount) * 100)
End If
Next
I use the SetIntveral Javascript methods to check for the value of the global variable every 2 seconds:
var progStat;
setInterval(function() {
progStat = <%=progressStatus%>;
document.write(progStat + "\n");
}, 2000);
Through debugging I checked that the global Variable in the Code behind is calculated and changed correctly. Anyway, Javascript keeps the initial Value of 0.
I would be glad if someone could help me with that problem!
Thank you very much everybody,
Max
When you use syntax like that:
progStat = <%=progressStatus%>;
progressStatus value is retrieved once and converted to string when page is rendered. At that time value is 0. It isn't retrieved from server every time you call that script.
It means javascript function rendered on your page looks like:
progStat = 0;
When you keep calling that function multiple times client-side it does not change as page isn't re-rendered.
You need to make use of an Ajax call to retrieve the value from the server. Use the result from the call together with JQuery and then update the UI
I'm writing a GUI extension and using the Anquilla framework to get a list of Keywords within a Category. I'm obtaining an XML document for the list of keywords then working with that document within my extension.
My problem is that the returned XML doesn't contain the Keyword's 'Description' value. I have the Title and Key etc.
My original code looks like this:
var category = $models.getItem("CATEGORYTCMID:);
var list = category.getListKeywords();
list.getXml();
A typical node returned is this:
<tcm:Item ID="tcm:4-1749-1024"
Type="1024" Title="rate_one" Lock="0" IsRoot="true"
Modified="2012-12-17T23:01:59" FromPub="010 Schema"
Key="rate_one_value" IsAbstract="false"
CategoryTitle="TagSelector"
CategoryID="tcm:4-469-512" Icon="T1024L0P0"
Allow="268560384" Deny="96" IsNew="false"
Managed="1024"/></tcm:ListKeywords>
So I've tried using a Filter to give me additional column information:
var filter = new Tridion.ContentManager.ListFilter();
filter.columns = Tridion.Constants.ColumnFilter.EXTENDED;
var list = category.getListKeywords(filter);
Unfortunately this only gives the additional XML attributes:
IsShared="true" IsLocalized="false"
I'd really like the description value to be part of this XML without having to create a Keyword object from the XML. Is such a thing possible?
cough any ideas? cough
I'm afraid you'll have to load the Keyword itself to get the Description.
It's not used in any lists, so it's not returned in the XML.
You could always create a List Extender to add this information to the list, but try to be smart about it since this extender will execute everytime a GetList is called.
Won't save you from having to open every keyword in the list, but you'll be doing it server-side (with Core Service/NetTcp for instance) which will probably be easier and faster than opening each keyword with Anguilla.
In this instance I only need the one keyword, so I simply get it from the CMS. Getting an object in Anguilla is a bit weird, here's the code:
In your main code area:
var selectedKy = $models.getItem("TcmUriOfKeywordHere");
if (selectedKy.isLoaded()) {
p.selectedKy = selectedKy;
this.onselectedKyLoaded();
} else {
$evt.addEventHandler(selectedKy, "load", this.onselectedKyLoaded);
selectedKy.load();
}
It's worth noting how I store the keyword in the properties of the item, so I can obtain it in the onselectedKyLoaded function
The function called once the item is loaded
ContentBloom.ExampleGuiExtension.prototype.onselectedKyLoaded = function (event) {
var p = this.properties;
var selectedDescription = p.selectedKy.getDescription();
// do what you need to do with the description :)
};
I resolved this, thanks to the answer here: https://stackoverflow.com/a/12805939/1221032 - Cheers Nuno :)