knockout : table in each option in drop-down - javascript

I want have table with two columns in each <option> in me <select>.
I tried this JSFIDDLE-source. But bindings in <span> isn't working
<span data-bind="text : countryName"></span>
<span data-bind="text : selectedCountry"></span>
Any ideas? Or another solution?
EDIT

While you can't style the contents of a you can use something like Twitter's excellent Bootstrap framework for a similar effect.
http://jsfiddle.net/marrok/QdjPt/
<div class="btn-group">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
<span class="name" data-bind="text: selectedItem().name"></span>
<span class="desc" data-bind="text: selectedItem().desc"></span> <span class="caret"></span>
</a>
<ul class="list dropdown-menu" data-bind="foreach: items ">
<!-- I should be able to use 'click' here but I'm not sure why it doesn't work. -->
<li class="item" data-bind="event: {mouseover : function(){$root.selectedIndex($index())}}">
<span class="name" data-bind="text: name"></span>
<span class="desc" data-bind="text: desc"></span>
</li>
</ul>
</div>
Javascript:
var Thing = function(name, desc) {
var self = this;
self.name = ko.observable(name);
self.desc = ko.observable(desc);
};
var AppModel = function() {
var self = this;
self.items = ko.observableArray([
new Thing(1, "Thing One"),
new Thing(2, "Thing Two"),
new Thing(3, "Thing Three"),
new Thing(4, "Thing Four")]);
self.selectedIndex = ko.observable(0);
self.selectedItem = ko.computed(function() {
return self.items()[self.selectedIndex()];
})
};
ko.applyBindings(new AppModel());​

Related

How to display loader symbol ONLY beside a specific item which was clicked in ng-repeat

The problem here is, the loader symbol is getting displayed beside every item in the ng-repeat array. How can I display the loader symbol just beside the item which was clicked
I tried using $index but no luck.
I created a working example using CodePen. Could anyone please guide how to do it.
Below are excerpts from my app.
HTML Code
<ul>
<li class="listItems" ng-repeat="user in userDetails">
{{user.name}}, {{user.job}}
<span class="glyphicon glyphicon-ok markAsChecked" ng-click="markAsChecked()"></span>
<span ng-show="isLoaderActivated" class="glyphicon glyphicon-repeat loader"></span>
</li>
</ul>
JS Code
$scope.markAsChecked = function() {
console.log("clicked");
$scope.isLoaderActivated = true;
$timeout(function() {
return ($scope.isLoaderActivated = false);
}, 2000);
};
You can find solution CodePan
Html Code
<ul>
<li class="listItems" ng-repeat="user in userDetails">
{{user.name}}, {{user.job}}
<span class="glyphicon glyphicon-ok markAsChecked" ng-click="markAsChecked(user)"></span>
<span ng-show="user.isLoaderActivated" class="glyphicon glyphicon-repeat loader"></span>
JS Code
$scope.markAsChecked = function(item) {
console.log("clicked");
item.isLoaderActivated = true;
$timeout(function() {
item.isLoaderActivated = false;
}, 2000);
};
You can pass object in your example is user to the function and do the actions on it instead $scope which is global
Html:
<li class="listItems" ng-repeat="user in userDetails">
{{user.name}}, {{user.job}}
<span class="glyphicon glyphicon-ok markAsChecked" ng-click="markAsChecked(user)"></span>
<span ng-show="user.isLoaderActivated" class="glyphicon glyphicon-repeat loader"></span>
</li>
Controller:
$scope.markAsChecked = function(item) {
console.log("clicked");
item.isLoaderActivated = true;
$timeout(function() {
item.isLoaderActivated = false;
}, 2000);
};

Foreach: Toggle each icon - KnockoutJS

I am trying to toggle the plus symbol to minus sign, once after immediately that section get clicked and expanded. Following the code I have tried.
<div>
<ul style="list-style: none">
<li data-bind="foreach: model">
<div id="panelHeading">
<i class="fa fa-plus" style="padding-right: 5px;">+</i>
<span data-bind="text: Main"></span>
</div>
<div id="panelContent" data-bind="if: show">
<ul id="clustersList" data-bind="foreach: Sub" style="list-style: none">
<li><span style="padding-left: 20px;" data-bind="text: $data"></span></li>
</ul>
</div>
</li>
</ul>
</div>
=== JS ====
var viewModel = function() {
var self = this;
self.model = ko.observableArray([{
Main: "Main1",
Sub: ["hello", "hi"],
show: ko.observable(false)
}, {
Main: "Main2",
Sub: ["one", "two"],
show: ko.observable(false)
}]);
self.toggleShow = function (item) {
$('this a').find('i').toggleClass('fa fa-plus fa fa-minus');
var index = self.model.indexOf(item);
if (item.show())
self.model()[index].show(false);
else
self.model()[index].show(true);
}
}
ko.applyBindings(new viewModel());
Please check my Fiddle here.
Any suggestion would be helpful.
Just change your HTML to apply the correct style based on the current value of show:
<i class="fa" data-bind="css: { 'fa-plus': !show(), 'fa-minus': show() }"></i>
And in your JS:
self.toggleShow = function (item) {
item.show(!item.show());
};
See Fiddle

autocomplete search in ng-repeat in angularjs?

I my code i have 3 ng-repeats based on key press event value i am getting data from service and iam consuming
my html code is:
<div class="input-group" ng-controller="sidemenu">
<input class="form-control" placeholder="Enter location, builder or project" ng-model="NodeId_1" autofocus ng-keyup="getValue($event.keyCode)"/>
<div class="search-datalist" ng-if="showsearch">
<ul ng-if="resultOfBuldDet.length>0">
<span class="result-hd">Builders</span>
<li ng-repeat="bud in resultOfBuldDet" ng-class="{active :2}" ng-click="searchFilter(bud)"><i class="fa fa-map-marker"></i> {{bud.builders_name}}</li>
</ul>
<ul ng-if="resultOfPropDet.length>0">
<span class="result-hd">Properties</span>
<li ng-repeat="prop in resultOfPropDet" ng-click="searchFilter(prop)"><i class="fa fa-map-marker"></i> {{prop.property_name}} ,{{prop.hp_city.city_name}},{{prop.hp_location.location_name}} </li>
</ul>
<ul ng-if="resultOfCityDet.length>0">
<span class="result-hd">cities</span>
<li ng-repeat="city in resultOfCityDet" ng-click="searchFilter(city)"><i class="fa fa-map-marker"> </i> {{city.city_name}}</li>
</ul>
<ul ng-if="resultOfLocaDet.length>0">
<span class="result-hd">Location</span>
<li ng-repeat="loc in resultOfLocaDet" ng-click="searchFilter(loc)"><i class="fa fa-map-marker"></i> {{loc.location_name}},{{loc.hp_city.city_name}}</li>
</ul>
<ul ng-if="resultOfSubLocaDet.length>0">
<span class="result-hd">sub Location</span>
<li ng-repeat="subloc in resultOfSubLocaDet" ng-click=" searchFilter(subloc)"><i class="fa fa-map-marker"></i> {{subloc.sub_location_name}},{{subloc.hp_location.location_name}},{{subloc.hp_location.hp_city.city_name}}</li>
</ul>
</div>
</div>
my controller js code:
sidemenu.controller('sidemenu', ['$scope', '$rootScope', 'allServices'
function(a, b,e) {
a.getValue = function(key) {
if (key == 8 && a.NodeId_1.length <= 2) {
a.resultOfPropDet = "";
a.resultOfBuldDet = "";
a.resultOfLocaDet = "";
a.resultOfCityDet = "";
a.resultOfSubLocaDet = "";
}
if (a.NodeId_1.length > 2) {
e.searchList(a.NodeId_1).then(function(result) {
a.resultOfPropDet = result.data.resultOfPropDet;
a.resultOfBuldDet = result.data.resultOfBuldDet;
a.resultOfLocaDet = result.data.resultOfLocaDet;
a.resultOfCityDet = result.data.resultOfCityDet;
a.resultOfSubLocaDet = result.data.resultOfSubLocaDet;
a.showsearch = true;
}, function(error) {
});
}
}
});
so when i am moving up and down arrows in keyboard.how to highlight the particular rows and trigger the particular function
like this

Backbone sort collections by click on non template elements

I want to sort my backbone collections by clicking non backbone template elements
In brief , i have 2 Sorting options named "Sort by date" and "Sort by name". when i click these elements i need to sort my collection in my backbone view
View template :
<ul>
<li>Sort By date</li>
<li>Sort By name</li>
</ul>
<script type="foo/bar" id='videos-thumbnail'>
<div class="col-md-4">
<div class="video-thumbnail-item">
<div style="background-image:url(recenty_added/recentlyadded2.jpg);" class="video-thumbnail"> </div>
<div class="video-details">
<div class="video-title text-purple uppercase"><%= title %></div>
<div class="video-date"><%= date %></div>
</div>
<div class="video-thumbnail-checkbox"> <span class="custom-checkbox">
<input type="checkbox" class="playlist-checkbox" name="addto-playlist[]">
</span>
<% if (is_rights_managed== true) { %>
<div class="checkbox-label-light">RM</div>
<% } else {%>
<div class="checkbox-label-light"></div>
<% } %>
</div>
<div class="video-thumbnail-options"> <span title="Download" class="option-parts"> <i class="fa fa-download"></i> </span> <span title="Edit" class="option-parts"> <i class="fa fa-pencil"></i> </span> <span title="More Information" class="option-parts"> <i class="fa fa-info-circle"></i> </span> <span title="View Details" class="option-parts"> <i class="fa fa-search"></i> </span> <span title="Add to Clipbins" class="option-parts"> <i class="fa fa-folder-open"></i> </span> <span title="Add to Cart" class="option-parts"> <i class="fa fa-cart-plus"></i> </span> <span title="Contact me about this Clip" class="option-parts"> <i class="fa fa-envelope"></i> </span> </div>
</div>
</div>
</script>
<div class="row" id="thumbnail_target"> </div>
App :
//backbone & underscore
$(function() {
var Videos = Backbone.Model.extend();
var VideoList = Backbone.Collection.extend({
model: Videos,
url: 'https://api.myjson.com/bins/4mht3'
});
var videos = new VideoList();
var VideoView = Backbone.View.extend({
el: "#thumbnail_target",
template: _.template($('#videos-thumbnail').html()),
render: function(eventName) {
_.each(this.model.models, function(video){
var videoTemplate = this.template(video.toJSON());
$(this.el).append(videoTemplate);
}, this);
return this;
},
});
var videosView = new VideoView({model: videos});
videos.fetch({
success: function() {
videosView.render();
videoslistView.render();
}
});
});
Am newbie to backbone and underscore, am not sure how to make this work
Example fiddle : Fiddle
Since you have access to collection outside view, you can simply use jquery to bind an event handler for the <li>, which updates the collections comparator and sorts it. Then have the view re-render itself when a sort event occurs on the collection.
for the demo I'm using string and number types of sort attributes so that I can directly set it as comparator. You should write a custom comparator function that handles sorting based on different types of arguments like string, number, date etc. Updated fiddle
//backbone & underscore
$(function() {
var Videos = Backbone.Model.extend();
var VideoList = Backbone.Collection.extend({
model: Videos,
url: 'https://api.myjson.com/bins/4mht3'
});
var videos = new VideoList();
var VideoListView = Backbone.View.extend({
el: "#thumbnail_target",
template: _.template($('#videos-thumbnail').html()),
initialize: function() {
this.listenTo(this.collection, 'sort', this.render);
},
render: function(eventName) {
this.$el.empty();
_.each(this.collection.models, function(video) {
var videoTemplate = this.template(video.toJSON());
this.$el.append(videoTemplate);
}, this);
return this;
},
});
var videosView = new VideoListView({
collection: videos
});
videos.fetch({
success: function(collection) {
videosView.render();
}
});
$('#sortBy').on('click', 'li', function() {
var category = $(this).text().split('Sort By ')[1];
videos.comparator = category;
videos.sort();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<ul id="sortBy">
<li>Sort By average</li>
<li>Sort By title</li>
</ul>
<script type="foo/bar" id='videos-thumbnail'>
<div class="col-md-4">
<div class="video-thumbnail-item">
<div style="background-image:url(recenty_added/recentlyadded2.jpg);" class="video-thumbnail"></div>
<div class="video-details">
<div class="video-title text-purple uppercase">
<%=t itle %>
</div>
<div class="video-date">
<%=d ate %>
</div>
</div>
<div class="video-thumbnail-checkbox"> <span class="custom-checkbox">
<input type="checkbox" class="playlist-checkbox" name="addto-playlist[]">
</span>
<% if (is_rights_managed==t rue) { %>
<div class="checkbox-label-light">RM</div>
<% } else {%>
<div class="checkbox-label-light"></div>
<% } %>
</div>
<div class="video-thumbnail-options"> <span title="Download" class="option-parts"> <i class="fa fa-download"></i> </span> <span title="Edit" class="option-parts"> <i class="fa fa-pencil"></i> </span> <span title="More Information" class="option-parts"> <i class="fa fa-info-circle"></i> </span>
<span
title="View Details" class="option-parts"> <i class="fa fa-search"></i>
</span> <span title="Add to Clipbins" class="option-parts"> <i class="fa fa-folder-open"></i> </span> <span title="Add to Cart" class="option-parts"> <i class="fa fa-cart-plus"></i> </span> <span title="Contact me about this Clip" class="option-parts"> <i class="fa fa-envelope"></i> </span>
</div>
</div>
</div>
</script>
<div class="row" id="thumbnail_target"></div>
Looks like you want global vent for in-app events
$(function() {
var channel;
channel = _.extend({}, Backbone.Events);
$('.some-sort-dy-date-element').on('click', function() {
channel.trigger('app:sort', {sortBy: 'date'});
});
$('.some-sort-dy-name-element').on('click', function() {
channel.trigger('app:sort', {sortBy: 'name'});
});
// rest logic
});
Your VideoList collection should listen to channel event like that (example for initialize):
var VideoList = Backbone.Collection.extend({
initialize: function initialize() {
this.listenTo(channel, 'app:sort', function someSortLogic() {
this.trigger('your.app.ns.videos.SORTED');
});
}
});
var VideoView = Backbone.View.extend({
initialize: function initialize() {
this.listenTo(this.collection, 'your.app.ns.videos.SORTED', this.render);
}
});

Keep track of tabs with knockoutjs + twitter bootstrap

I'm trying to keep track of the selected tab in the view model but I can't seem to make it work.
In the following code when you click a tab the header will update correctly but the content of the tab is not displayed. If you remove , click: $parent.selectSection then the contents are shown but the header does not update.
Now if you remove the data-bind="css: { active: selected }" from the li then it seems to work when you click the tabs but the button to select the second tab doesn't.
How can I make this work?
See: http://jsfiddle.net/5PgE2/3/
HTML:
<h3>
<span>Selected: </span>
<span data-bind="text: selectedSection().name" />
</h3>
<div class="tabbable">
<ul class="nav nav-tabs" data-bind="foreach: sections">
<li data-bind="css: { active: selected }">
<a data-bind="attr: { href: '#tab' + name }
, click: $parent.selectSection" data-toggle="tab">
<span data-bind="text: name" />
</a>
</li>
</ul>
<div class="tab-content" data-bind="foreach: sections">
<div class="tab-pane" data-bind="attr: { id: 'tab' + name }">
<span data-bind="text: 'In section: ' + name" />
</div>
</div>
</div>
<button data-bind="click: selectTwo">Select tab Two</button>
JS:
var Section = function (name) {
this.name = name;
this.selected = ko.observable(false);
}
var ViewModel = function () {
var self = this;
self.sections = ko.observableArray([new Section('One'),
new Section('Two'),
new Section('Three')]);
self.selectedSection = ko.observable(new Section(''));
self.selectSection = function (s) {
self.selectedSection().selected(false);
self.selectedSection(s);
self.selectedSection().selected(true);
}
self.selectTwo = function() { self.selectSection(self.sections()[1]); }
}
ko.applyBindings(new ViewModel());
There are several ways that you can handle this either using bootstrap's JS or by just having Knockout add/remove the active class.
To do this just with Knockout, here is one solution where the Section itself has a computed to determine if it is currently selected.
var Section = function (name, selected) {
this.name = name;
this.isSelected = ko.computed(function() {
return this === selected();
}, this);
}
var ViewModel = function () {
var self = this;
self.selectedSection = ko.observable();
self.sections = ko.observableArray([
new Section('One', self.selectedSection),
new Section('Two', self.selectedSection),
new Section('Three', self.selectedSection)
]);
//inialize to the first section
self.selectedSection(self.sections()[0]);
}
ko.applyBindings(new ViewModel());
Markup would look like:
<div class="tabbable">
<ul class="nav nav-tabs" data-bind="foreach: sections">
<li data-bind="css: { active: isSelected }">
<a href="#" data-bind="click: $parent.selectedSection">
<span data-bind="text: name" />
</a>
</li>
</ul>
<div class="tab-content" data-bind="foreach: sections">
<div class="tab-pane" data-bind="css: { active: isSelected }">
<span data-bind="text: 'In section: ' + name" />
</div>
</div>
</div>
Sample here: http://jsfiddle.net/rniemeyer/cGMTV/
There are a number of variations that you could use, but I think that this is a simple approach.
Here is a tweak where the active tab used the section name as a template: http://jsfiddle.net/rniemeyer/wbtvM/

Categories

Resources