I am using a listView control in my Windows8 JavaScript app and I am rendering the items on the page using some code which looks like:
listView.layout = new ui.GridLayout({
groupHeaderPosition: "top",
groupInfo: this.groupInfo,
itemInfo: this.computeItemSize
});
Now I want to do some action after these items are rendered on the page. Any idea where I can set a callback for this?
There are two ways of create a renderer: declare a WinJS.Binding.Template, or create a custom render function
WinJS.Binding.Template
To create a WinJS.Binding.Template, you use HTML markup to define a template for how an item is rendered. Within the template, you use data binding to associate properties of the HTML elements with fields in the data record
Custom render function
You can define custom render function for converting a data record into its HTML representation. The advantages of implementing a custom renderer are:
It can perform customized element recycling.
It can supply placeholder elements.
It can render items progressively.
It can make incremental requests for data, if needed.
The render function takes these parameters:
object renderItem(itemPromise, recycledElement)
itemPromise: a IItemPromise for the data for the item to render. With a synchronous datasource, the IItemPromise is usually complete, but with an async datasource, it will complete at some time in the future.
recycledElement : the DOM from a previous item that can be reused to display new content.
The render function must return either:
The root element of a DOM tree for the item.
An object that contains these properties:
element: the root element of a DOM tree for the item, or a promise that when completed will return the root element for the item.
renderComplete: a Promise that completes when the item is fully rendered.
The Entire information for the link is given below
http://msdn.microsoft.com/en-us/library/windows/apps/Hh781224.aspx#displaying_items_with_a_template_or_render_function
Hope it helps...Thanks
On your listview, listen for the loadingstatechanged event.
http://msdn.microsoft.com/en-us/library/windows/apps/hh700709.aspx
Related
I am using NetChart from ZoomCharts, It provides an option to filter nodes by providing a function in nodeFilter argument which is called by chart.updateFilters(). I want to know if there exists an event that is fired after updateFilters is completed and new chart with filtered nodes is rendered, so that I can get list of nodes that are currently rendered.
I found an event onChartUpdate but it doesn't work everytime chart.updateFilters() is called.
When you are calling chart.updateFilters() this triggers data update, where the nodes are validated against the filters in the next immediate rendering cycle. So, for now you can simply use setTimeout() and use api call nodes() to get the visible nodes. Alternatively, you can hook into nodeFilter() method to sync the data model state externally to keep the state always updated.
You can also request a new feature development if you need this feature in your project (write to support#zoomcharts.com)
Have a SAPUI5 application. Html view created by xml. JavaScript controllers. Some elements of this application, e.g. buttons are created somewhere dynamically within the controllers of the respective views. I.e. cannot use the id of an element to get it in the controller because the ids are dynamically created. Would like to get those dynamically created elements of the application to modify them, e.g. modify the buttons. What's the best way to trace a dynamically created element back to its code where it's created? E.g. how to trace a button back to it's origin in the JavaScript controller? It's a huge application and a view has multiple controller. I'm not just lazy.
The render function in the component's renderer class is what (eventually) creates the DOM element. You can inject a debugger statement into it like so:
let __buttonRender = sap.m.ButtonRenderer.render;
sap.m.ButtonRenderer.render = function() {
let control = arguments[1];
console.log('Creating button: ', control.sId);
debugger;
return __buttonRender.apply(this, arguments);
}
You can probably modify the control object based on the Id here. I'm not exactly sure what your end goal is here. The renderer is probably taking attributes and data from XML, so if you want to modify the buttons, I'd do it at the data source. The above could would allow you to hack the model before it reaches the DOM, but it's kinda nasty.
I'm pretty new to Backbone.js, loving it so far, but I'm having a little trouble trying to get relational data to render.
Within my Backbone view (called ImagesView) I have the following code:
// Render it
render: function () {
var self = this;
// Empty the container first
self.$el.html("")
// Loop through images
self.collection.each(function(img){
// convert `img` to a JSON object
img = img.toJSON()
// Append each one
self.$el.append(self.template(img))
}, self)
}
There are 3 images in the collection, and they are templated correctly with the above code. Within the img object is a user attribute, containing the User ID. I'm trying to return the user's details, and use these within the template instead of the ID. I'm doing that using the code below:
// Render it
render: function () {
var self = this;
// Empty the container first
self.$el.html("")
// Loop through images
self.collection.each(function(img){
// convert `img` to a JSON object
img = img.toJSON()
/* New code START */
// Each img has a `user` attribute containing the userID
// We'll use this to get their details
$.getJSON('/user/' + img.user, {}, function(json, textStatus) {
img.photographer = {
id: json.id,
username: json.username,
real_name: json.real_name
}
/* Moved 1 level deeper */
// Append each one
self.$el.append(self.template(img))
});
/* New code END */
}, self)
}
When I do this, the user's details are returned correctly and inserted into the template, but I now get 3 of each image returned instead of 1 (i.e. 9 in total), in a completely random order. What am I doing wrong? I'm open to using Backbone methods instead of the getJSON if that will make it easier, I just couldn't get it to work myself. I'm using underscore.js for the templating
The random order is likely caused by the requests being fired at very close intervals and responses returning out of the order they were fired in. I'm not sure why you're getting the multiple things, but if your template renders everything and you're calling that 3 times that could be it?
Anyway where I think you're going wrong is putting the responsibility of loading data into the render method. You'd want this to be abstracted so you have a good separation between data concerns and template concerns. As the ordering of the data is of interest, you'll want all 3 requests to have loaded before rendering. There's two different approaches you could take to this depending on if prior to loading this data you have sufficient data to render the view:
If you're waiting on all the data prior to rendering the view then you would want to render a different view (or template of this view) whilst the data is loaded and then replace that with a view showing all the data once it is loaded.
If you have sufficient data to render the view and what you are loading is supplementary, you'd want to render the view with the data you have in render and then once the other data is loaded use a custom method to modify the rendered view to include your data.
If you want to find out when all 3 requests are complete you can use http://api.jquery.com/jquery.when/
Question:
How can I get list of nested views (as they are defined in template) and reorder them? Or move view from one parentView to another?
For example, I'd like to switch places column with date and column with image, or hide any of them on user action
{{#data-grid}}
{{#grid-column}}
{{format-date date}}
{{/grid-column}}
{{#grid-column}}
{{#link-to 'somewhere'}}<img scr="i.png" title="hello"/>{{/link-to}}
{{/grid-column}}
{{/data-grid}}
Reason:
I'm implementing datagrid with reordering and hiding collumns in runtime. Declaring view classes for all cases and then using them in controller seems ugly to me.
Already tried to use ContainerView but could not find the way to fill childViews with template contents
UPDATE
Source code of data grid in current state: http://pastebin.com/E61e6WCt
If you want to implement this yourself, you should have a look at the CollectionView. Each of your columns should be one item in the content array of your view. Reordering the array should also reorder the DOM elements correctly.
Here is a rough sketch: Basically you are overriding createChildView within your subclass. You could pass strings into the content array indicating their type. Within createChildView you then can access the current item via the attrs object and its content property.
App.ColumnsCollectionView = Ember.CollectionView.extend({
content : ["date", "image"],
createChildView: function(viewClass, attrs) {
var itemFromContent = attrs.content; // is either 'date' or 'image'
if (itemFromContent == 'date') {
viewClass = App.YourDateColumnView;
} else {
viewClass = App.YourImageColumnView;
}
return this._super(viewClass, attrs);
}
});
I have a backbone viev which generates a list item view. In the render function it goes through the collection and generates each of the sub item views with some standard code as follows:
render: function () {
_(this.collection.models).each(function(item){
$this.appendItem(item);
}, this);
},
I would like to know how to access a specific view from the item list, say at position 0 or something. I want to be able to trigger a function from the item list view for that specific item.
Well, that depends on how the appendItem function is implemented, I guess is in there where you build the SubViews.
You can store each created SubView in an Array so the Array will offer you a way to manipulate the SubViews.
But if I can offer a piece of advice I would say that this is a code smell from the begining. Instead of trying to manipulate a concrete SubView you can manipulate the Model which is associated with the SubView and make the SubView to be listening to this change.
Then you will start to be thinking in manipulating Models instead of Views.