How to databind JQuery Mobile with Knockout and Upshot - jquery-mobile

I am trying to build a JQuery Mobile UI which uses upshot for getting data from the service and then uses Knockout.js to bind the values to a list. I am able to populate the data however, the JQuery mobile styles are not getting rendered.
Here is my code. Any help in this regard would be really appreciated.
<h2>Projects (<span data-bind="text: projects().length"></span>)</h2>
<ul data-inset="true" data-bind="foreach: projects" data-role="listview" data-theme="e" data-dividertheme="c" data-filter="true">
<li>
Project Type : <label data-bind="text: ProjectType"></label>
Description : <label data-bind="text: Description"></label>
</li>
</ul>
<p></p>
#(Html.UpshotContext(bufferChanges: true).DataSource<ProjectServiceController>(x => x.GetProjects()))
<script type="text/javascript">
$(function () {
var dataSource = upshot.dataSources.Projects.refresh();
var ProjectsViewModel = {
projects: dataSource.getEntities()
};
ko.applyBindings(ProjectsViewModel);
});
</script>

The refresh() call is asynchronous, so you can provide a callback function that is executed after the refresh. jQueryMobile docs say that if you add items you need to refresh the listview after the items are created: http://jquerymobile.com/demos/1.0.1/docs/lists/docs-lists.html
Here's an example of how you might do that:
var dataSource = upshot.dataSources.Projects.refresh(function() {
$("ul").listview('refresh');
});

Related

Knockout foreach with a where clause

This sytax is in razor that I am converting to knockoutJS.. any help much appreciated..
Where ItemStatus.Active is 0 in an enum in c# ( backend )
#foreach (var employee in Employees.Where(x => x.Status == ItemStatus.Active))
{
<div class="someclass”>
<span class="label">Name:</span>
<span class="value">#employee.Name</span>
</div>
}
How do I replicate this logic in knockout foreach, ie I only want to show employees who are currently active or employed
Thank you
Any JavaScript expression can be used in Knockout bindings.
So you could use the filter function (ES6):
<!-- ko foreach: Employees.filter(employee => employee.Status == 0) -->
...
<!-- /ko -->
Or any other method of filtering:
<!-- ko foreach: ko.utils.arrayFilter(Employees.filter, function(employee) { return employee.Status == 0; }) -->
...
<!-- /ko -->
Razor runs server-side. So, you can't use Employees with knockout bindings which are apllied client-side. You need to hand over this Employees data to a javascript variable, and then bind that using knockout which will run client-side, after the page loads.
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script>
// cretes a js array of active employees
var activeEmployees = #Html.Raw(JsonConvert.SerializeObject(Employees.Where(x => x.Status == ItemStatus.Active)));
var viewModel = {
Employees: ko.observableArray(activeEmployees)
}
ko.applyBindings(viewModel);
</script>
Use the foreach binding in your HTML like this (Here Employees refers to the property of your knockout viewModel, not MVC)
<!-- ko foreach: Employees -->
<div class="someclass">
<span class="label">Name:</span>
<span class="value" data-bind="text:Name"></span>
</div>
<!-- /ko -->
You also need to add #using Newtonsoft.Json to the top your cshtml file for JsonConvert

How do I open a tab from with jQuery UI Tabs from an link outside of the div?

This may be a little difficult to explain, but I'll try my best. I have a product page with two tabs, full description and video. These are done using jQuery UI Tabs.
Above this section of the page I have a product image with thumbnails...but I want one of the thumbnails to be a link to see the video (which of course is contained in the video tab).
If I load the page as site.com/product#video it does load up the correct tab...but when the tab is not active, and I use a link outside of the #tab div, (ex: Video), it doesn't do anything.
How can I get a link to open the tab if it's not contained in the #tab div?
CODE
This code is outside of the tabs, and needs to open the #video tab
Open Video Tab
Tabs Code
<div id="tabs" class="ui-tabs ui-widget ui-widget-content ui-corner-all">
<ul class="product-tabs ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">
<li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover">Full Description</li>
<li class="ui-state-default ui-corner-top">Video</li>
</ul>
<div class="product-collateral">
<div class="box-collateral box-description">
<div id="description" class="ui-tabs-panel ui-widget-content ui-corner-bottom">
Content
</div>
<div id="video" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide">
<h2 class="video">Video Content</h2>
</div>
</div>
</div>
</div>
What worked for me was this:
Html
Open Description Tab
Open Video Tab
<div id="tabs">
<ul>
<li>
Full description
</li>
<li>
Video content
</li>
</ul>
<div class="product-collateral">
<div class="box-collateral box-description">
<div id="description">
Content
</div>
<div id="video">
<h2 class="video">Video Content</h2>
</div>
</div>
</div>
</div>
Javascript
$(document).ready(function () {
$('#tabs').tabs();
$('.open-tab').click(function (event) {
var tab = $(this).attr('href');
$('#tabs').tabs('select', tab);
});
});
So what this does is provide a link to both the description and video tabs, which are selected when the link is clicked.
From here we can see that when selecting a particular tab, we can use either a zero-based index or the href fragment which points to the tab we wish to display.
This is why the href attributes of the a elements match up with the Ids of the div elements - when one is clicked its href fragment is then used to set the selected tab.
Update for jQuery UI 1.11
As jQuery UI has evolved, so to has the API for setting the active tab. As of jQuery UI 1.11, the following code will select the active tab:
//Selects by the zero-based index
$('#tabs').tabs("option", "active", index);
Now because we now have to provide a zero-based index, the code I initially provided will no longer work.
What we need now is an index that can actually be used. One approach is:
$('.open-tab').click(function (event) {
var index = $("selector-of-clicked-tab").index();
$('#tabs').tabs("option", "active", index);
});
Another is to use HTML5 data- attributes:
Open Description Tab
Open Video Tab
So you can do this when handling the click of these links:
$('.open-tab').click(function (event) {
$('#tabs').tabs("option", "active", $(this).data("tab-index"));
});
use jQuery:
$( "#tabs" ).tabs({ active: tabNumber });
Remember, that the indexation starts from 0
Using jquery, bind a click event to your link that opens the tab you want.
$('#tabopenlink').click(function() {
$('#tabs').tabs({active: tabidx});
});
I use mini plug-in.
(function($) {
$.fn.tabremote = function(options) {
var settings = $.extend({
panel: "#tabs",
to: "data-to",
}, options );
$this=$(this);
$panel=$(settings.panel);
$this.click(function(){
if($(this).attr("href"))
{var tos=$(this).attr("href");}
else
{var tos=$(this).attr(settings.to);}
to=tos.match(/\d/g);
$panel.tabs({active: to-1});
return false;
});
return this;
}
})(jQuery);
Opens the tab using href or any element.
id panel must contain the number of the panel. Example (1-tabs, tabs-2, ...)
Plugin subtracts 1 and open the panel. Tabs (active, (number of id -1))
Use
$("button.href").tabremote({panel:"#tabs",to:"data-href"});
panel:"#tabs" // container panel
to:"data-href" // attribute name with value
function openTabByLink(link) {
$("#tabs").find("ul li[aria-controls='"+link+"'] a").trigger("click");
}
If you use twitter bootstrap instead of jquery ui, it will be very simple.
Just add data-toggle="tab" and put the link wherever you want in the page:
Open Video Tab
For jQuery UI 1.11
HTML:
<div id="tabs">...</div>
...
Open Video Tab
JS:
$('.open-tab').click(function () {
$("#tabs").tabs('option','active',$('#tabs a.ui-tabs-anchor[href="'+$(this).attr('href')+'"]').index('#tabs a.ui-tabs-anchor'));
});

events are not triggerring after added by append method in jquery

<div class="sortable-sections">
<fieldset class="section draggable" id="flSectionType">
<div class="btn-drag section-handle hidden-view">
</div>
<div class="section-header">
<span class="section-label">Job Requirements</span> <a class="section-info" href="#more-info"
title="Minimum Education, Minimum Work Experience, Required Licenses/Certifications, Required Skills, Knowledge, and Abilities needed to perform the job.">
?</a>
</div>
<div class="sortable-items">
</div>
<a class="section-add-item hidden-view" id="addJR" href="#add-item" data-item='{"id":"addJR","template":"requirement","item_type":"Job Requirement"}'>
Add a new Job Requirement</a>
</fieldset>
<fieldset class="section draggable">
</fieldset>
<fieldset class="section draggable">
</fieldset>
<div>
The above code will generate a list of sections which can be dragged with in the sortable-sectons.
I am using the following script to remove sections manually and adding it back to sortable-sections, but it is not registering the jquery events.
var $section = $('.sortable-sections').find($('#flSectionType');
$('.sortable-sections').find($('#flSectionType').remove();
......
.......
$('.sortable-sections').append($section.val());
After appending the section, the event which are registered for the section-add-item css classes are not triggering.
Note:
instead of "on" used the "live" method. but it is not holding all attributes.
Edit:
Event code:
$('.section-add-item').on('click', function (e) {
that.addSection(this);
e.preventDefault();
});
instead of drag and drop, manually i am ordering the section on initial load.
.section-add-item must already exist when adding the event and the usage of on is wrong
$('body').on('click', '.section-add-item', function (e) {
});
instead of the body you can add another parent of .section-add-item that already exists before .section-add-item is created.

jquerymobile pages and Phonegap deviceready event onLoad

I know this has been discussed before, but with no results for me.
The problem is that deviceready() is only fired once, the first time on "list" page. I can´t get it to work on article pages. And when I go back from a "article" page to "articlelist" the event is still out of work. I need the menubutton operative in every data-role="page".
The js:
<script type='text/javascript'>
function onLoad() {
document.addEventListener("deviceready", onDeviceReady, false);
}
function onDeviceReady() {
document.addEventListener("menubutton", onMenuKeyDown, false);
}
function onMenuKeyDown() {
alert('Menu pressed');
}
</script>
The HTML:
<body onload="onLoad()">
<div id="list" data-role="page">
<ul id="articleList" data-role="listview">
<li id="list1"><a id="link1" href="#article1"></li>
<li id="list2"><a id="link1" href="#article2"></li>
</ul>
</div>
<div id="article1" data-role="page">Content</div>
<div id="article2" data-role="page">Content</div>
I'm with: cordova-1.5.0 /jquery.mobile-1.1.0-rc.2 /jquery-1.7.1 /Android
Any help please?
I just quickly tested this in the app I'm working on right now and it works. Phonegap-1.6.1 and jquery.mobile-1.1.0 final
Perhaps you should try upgrading your phonegap and jquery.mobile

jQuery Mobile - How to mobile-ize a checkbox rendered via jQuery Templates

On a jQuery Mobile site I have elements of a <ul> being populated by jQuery Templates, filling out <li> items so something like this:
<ul>
</ul>
<button>Fill</button>
<script type="text/x-jquery-tmpl" id="tmpl-items">
<li><input type="checkbox" name="guys" /> ${FirstName} ${LastName}</li>
</script>
<script type="text/javascipt">
$('this-page-id').live('pageinit', function() {
$('button').click(function() {
$('#tmpl-items').tmpl(MyApp.Model)
.appendTo('ul')
});
})
</script>
Everything works, except the checkbox renders as a normal checkbox, not a cool jquery-mobilized checkbox. I know that the trick is to call "refresh" on the widget but I have no idea what widget I should be using - there is no data-role here. Does anybody know?
Can you triggering a create on the ul,like this $('ul').trigger('create');

Resources