WordPress database error: [INSERT, UPDATE command denied to user '51213-2'@'10.10.20.185' for table 'wp_options']INSERT INTO `wp_options` (`option_name`, `option_value`, `autoload`) VALUES ('_transient_doing_cron', '1714261490.7505009174346923828125', 'yes') ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)
\nThe ListView is the most used control of WinJS in Windows 8 metro apps. It’s build with three things : the data, a layout and an item templates. <\/p>\n
In this post, we will discover the different way to provide an item template and how to customize it.<\/strong><\/p>\n \n<\/p>\n The easiest thing is to create an item template in the html. As you can see, data binding are defined to push the value in the html element<\/strong>. For example, the title property of the data item will be pushed as the text content of the h4 element with the “item-title” class. The “select” is a special helper which query the DOM for the provided selector<\/strong> and retrieve the first element which match. In your case, the item template is retrieved using its class name. You could also provide the item template in the code-behind js file : The listview then use the item template to display each of the item in its datasource. One html element is created by data and the data bindings are applied. You can style each of them using the class name of the item template’s inner elements. A more flexible way of providing html for each item in the data source is to define a templating function<\/strong>. The templating function takes two arguments : the first is a promise to the actual data item and the second is an item to recycle <\/strong>(more on that later).<\/p>\n You can assign a templating function to a listview as you have already done for the template before. Now let’s define a basic templating function which returns an html element for a given data item<\/strong>. It returns the same html that we used in the first example. \/\/"wait" for the data item \/\/Create a main element \/\/Create the title and set the text in it \/\/Create the content and set the text in it \/\/Return the html for the given data });<\/p>\n } What is done ? First, we wait to get the item data using the itemPromise<\/strong>. Once we’ve got it, we create an html element from scratch (ie the document) and we fill it with the values of the data item. Notice that there is no binding involved, this is all hand made. We also set the different class on the elementw as it was done in the first html fragment. <\/p>\n As you can see, the templating function is returning a promise to a single html element representing the data item<\/strong>. <\/p>\n If you run this code, you will get the same view as in the first sample. Nothing more at this point.<\/p>\n Often, you fetch the data from the web and you don’t know when it will be availabe and how fast it will be to retrieve it. When it takes a lot of time, the view is no more responsive because the templating function wait for the data before to return the html element.<\/p>\n You can then use the templating function to return a placeholder instead of the actual representation<\/strong>. Because you need to fill the item with the actual data, you also have to provide a promise which will complete when the data is available and the actual html element representing it created.<\/p>\n Instead of returning a promise to an html element, you return an object defining two properties : element and rendercomplete.<\/strong>. element is a placeholder and renderComplete is a promise which complete when the item template is fully rendered. Let’s improve the previous example to use this advanced technique : \/\/Create a main element \/\/Create the title \/\/Create the content mainElementDiv.appendChild(h6Content);<\/p>\n var toReturn = \/\/promise which set the value in the place holder from the data \/\/Simulate latency \/\/Set the actual values in the placeholder \/\/listView.recalculateItemPosition(); return toReturn; The snippet is in fact quite similar to the previous one. First I create the place holder with some text telling the user to wait because <\/strong>it’s loading. Then I return the previously mentioned item defining the renderComplete property as a promise. This promise sets the actual values in the placeholder from the retrieved data<\/strong>. I wanted to simulate some latency so I added a WinJS.Promise.Timeout but it’s not necessary.<\/p>\n <\/p>\n The ListView don’t know the actual size of your elements before to actually render them. You then have two solutions to fix it :<\/p>\n Here is an example of these strange screens : The templating function takes in fact one another parameter which is a recycled element. Then instead, of creating the item, you reuse the one the listview gives you and reasign the values in it as it has been done previously. Don’t forget to clear the text already in the recycled element<\/strong> otherwise the displayed data will be the previous one until the renderComplete promise is completed. Here is the previous snippet updated : var mainElementDiv; } else { var toReturn = return toReturn; Ok, all what we have seen it’s interesting but sometimes what you need is just a little modification of the rendered item depending of the data and with these techniques you are loosing all the binding benefits. Too bad.<\/p>\n In fact, you can still use the template and the bindings really easily. Let’s see the code : \/\/could have been done once elsewhere \/\/Wait for the item \/\/use the item template \/\/wrap the retrieved value for instant access \/\/Extend the rendercomplete promise \/\/do something depending of the data placeholder.appendChild(renderedElement);<\/p>\n }); var toReturn = { First, we retrieve the item template from the DOM. It can be done once when the page is loaded but here we do it each time for demonstration purpose. <\/p>\n Then we wait for the data to come and call the renderItem function of the item template and provide the data using the <\/strong> … (what ?) … WinJS.Promise.wrap<\/strong>. We can’t give the data because the render item wants an item promise but if we do so, we’ll have to wait for the data to come again (it can be loooonnnggg from the web) so instead we give a promise to the data we already have using the helpful WinJS.Promise.wrap function.<\/p>\n Finally the renderComplete promise of the itemtemplate is extended to do something on the rendered element depending of the data.<\/strong> We then have something (beautiful ?) to display : Yes, I did ! You can easily extend the previous snippet to create an item template selector. The only<\/em> things to do is to choose the correct template once the data is retrieved : \/\/could have been done once elsewhere \/\/Wait for the item var itemTemplate; \/\/use the item template return renderCompletePromise; And I first though it will be a short blog post \ud83d\ude41<\/p>\n Here are some interesting links for you if you need\/want more :<\/p>\nThe standard way<\/h1>\n
\nA template is a specific WinJS control : “WinJS.Binding.Template”. You can declare it as any other control using the data-win-control attribute. <\/strong>
\n[html]
\n <div class="itemtemplate" data-win-control="WinJS.Binding.Template">
\n <div class="item-info">
\n <h4 class="item-title"
\n data-win-bind="textContent: title"><\/h4>
\n <h6 class="item-subtitle win-type-ellipsis"
\n data-win-bind="textContent: content"><\/h6>
\n <\/div>
\n <\/div>
\n[\/html]<\/p>\n
\n
\nThis template is then provided to the listview in the HTML using the options :
\n[html]
\n <div class="itemslist"
\n data-win-control="WinJS.UI.ListView"
\n data-win-options="{ itemTemplate : select(‘.itemtemplate’) }"><\/div>
\n[\/html]<\/p>\n
\n [javascript]
\n var listView = element.querySelector(".itemslist").winControl;
\n listView.itemTemplate = element.querySelector(".itemtemplate");
\n [\/javascript]
\nPlease note that the html element is provided as an item template AND NOT a win control (because it’s not one).<\/p>\n
\n
\n<\/p>\nAnother way : using a templating function<\/h2>\n
\n
\nThis is a simple js function which could returns two different object :<\/strong><\/p>\n\n
\n[javascript]
\n var listView = element.querySelector(".itemslist").winControl;
\n listView.itemTemplate = myTemplatingFunction;
\n [\/javascript]<\/p>\n
\n[javascript]
\nfunction myTemplatingFunction(itemPromise) {<\/p>\n
\n return itemPromise.then(function (item) {<\/p>\n
\n var mainElementDiv = document.createElement("div");
\n WinJS.Utilities.addClass(mainElementDiv, "item-info");<\/p>\n
\n var h4Title = document.createElement("h4");
\n WinJS.Utilities.addClass(h4Title, "item-title");
\n h4Title.innerHTML = item.data.title;
\n mainElementDiv.appendChild(h4Title);<\/p>\n
\n var h6Content = document.createElement("h6");
\n WinJS.Utilities.addClass(h6Content, "item-subtitle win-type-ellipsis");
\n h6Content.innerHTML = item.data.content;
\n mainElementDiv.appendChild(h6Content);<\/p>\n
\n return mainElementDiv;<\/p>\n
\n[\/javascript]<\/p>\nTemplating function : advanced scenario<\/h2>\n
\n[javascript]
\n{
\n element: element,
\n renderComplete: itemPromise.then(function (item) { \/* some code here *\/ }
\n}
\n[\/javascript]<\/p>\n
\n[javascript]
\nfunction myAdvancedTemplatingFunction(itemPromise) {<\/p>\n
\n var mainElementDiv = document.createElement("div");
\n WinJS.Utilities.addClass(mainElementDiv, "item-info");<\/p>\n
\n var h4Title = document.createElement("h4");
\n WinJS.Utilities.addClass(h4Title, "item-title");
\n h4Title.innerHTML = "Loading …";
\n mainElementDiv.appendChild(h4Title);<\/p>\n
\n var h6Content = document.createElement("h6");
\n WinJS.Utilities.addClass(h6Content, "item-subtitle win-type-ellipsis");<\/p>\n
\n {
\n \/\/placeholder
\n element: mainElementDiv,<\/p>\n
\n renderComplete: itemPromise.then(function (item) {<\/p>\n
\n return WinJS.Promise.timeout(Math.random() * 3000)
\n .then(function () {<\/p>\n
\n mainElementDiv.querySelector(".item-title").innerHTML
\n = item.data.title;
\n mainElementDiv.querySelector(".item-subtitle").innerHTML
\n = item.data.content;<\/p>\n
\n });
\n }),
\n };<\/p>\n
\n}
\n[\/javascript]<\/p>\n\n
\n<\/p>\nUI virtualization – recycling<\/h2>\n
\nIf the listview already has created a lot of element, it can be better for performance sake to reuse them instead of create them each time we need one<\/strong>. This can be considered as UI virtualization and this is exactly what the listview will try to do !<\/p>\n
\n[javascript]
\nfunction myRecyclingTemplatingFunction(itemPromise, recycled) {<\/p>\n
\n if (recycled) {
\n\t \/\/use the recycled element and clear the values
\n\t \/\/already in it !
\n mainElementDiv = recycled;
\n \/\/Set the actual values in the placeholder
\n mainElementDiv.querySelector(".item-title").innerHTML = "Loading RECYCLING";
\n mainElementDiv.querySelector(".item-subtitle").innerHTML = "";<\/p>\n
\n\t\t\/* same as before *\/
\n }<\/p>\n
\n {
\n\t\t\/* same as before *\/
\n };<\/p>\n
\n}
\n[\/javascript]
\n<\/p>\nI love
can’t live without<\/del> Bindings !<\/h2>\n
\n[javascript]function myTemplatingFunctionWithBindings(itemPromise) {<\/p>\n
\n var itemtemplate = document.querySelector(".itemtemplate");
\n var placeholder = document.createElement("div");<\/p>\n
\n var renderCompletePromise =
\n itemPromise.then(function (item) {<\/p>\n
\n return itemtemplate<\/p>\n
\n .renderItem(WinJS.Promise.wrap(item))
\n .renderComplete<\/p>\n
\n .then(function (renderedElement) {<\/p>\n
\n if (item.data.number % 10 == 0) {
\n WinJS.Utilities.addClass(renderedElement.firstElementChild, "pinkElement");
\n }<\/p>\n
\n });<\/p>\n
\n element: placeholder,
\n renderComplete: renderCompletePromise
\n }
\n return toReturn;
\n}
\n[\/javascript]<\/p>\n
\n<\/p>\nDid you said item template selector ?<\/h2>\n
\n[javascript]function myItemTemplateSelector(itemPromise) {<\/p>\n
\n var defaultItemtemplate = document.querySelector(".itemtemplate");
\n var fancyItemtemplate = document.querySelector(".fancyItemtemplate");<\/p>\n
\n var renderCompletePromise =
\n itemPromise.then(function (item) {<\/p>\n
\n if (item.data.number % 10 == 0) {
\n itemtemplate = fancyItemtemplate;
\n } else {
\n itemtemplate = defaultItemtemplate;
\n }<\/p>\n
\n return itemtemplate.renderItem(WinJS.Promise.wrap(item)).renderComplete;
\n });<\/p>\n
\n}
\n[\/javascript]
\n<\/p>\nDo you want more ?<\/h2>\n