Reputation: 13
I know there is a lot of similar question on the subject, but I have been trying to solved this issue by my own and I was not able to do it, its been a week already.
What I'm trying to do is just to filter the list with a text box. code below:
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Magic Towns</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="css/styles.css">
<style>
html,
body {
font-family: Arial, sans-serif;
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<div class="menuContainer">
<span class="center" style="font-size:30px;cursor:pointer" onclick="openNav()">☰</span>
<div id="mySidenav" class="sidenav">
<a href="javascript:void(0)" class="closebtn" onclick="closeNav()">×</a>
<a href="#"><h1>Locations:</h1></a>
<form role="search">
<input type="text" data-bind="value: query, valueUpdate: 'keyup'" placeholder="Search...">
</form>
<div data-bind='with currentPlace' >
<div data-bind='foreach: placeList'>
<p href="#" class="whiteFont" data-bind='text: city, click: closeNav'></p>
</div>
</div>
</div>
</div>
<script src='js/sidebar.js'></script>
<script src="js/jquery-3.2.1.min.js"></script>
<script src="js/knockout-3.4.2.js"></script>
<script src="js/data.js"></script>
<script src="js/app3.js"></script>
</body>
</html>
javascript:
var Place = function(data) {
this.city = ko.observable(data.city);
this.lat = ko.observable(data.lat);
this.lng = ko.observable(data.lng);
};
var ViewModel = function() {
var self = this;
self.placeList = ko.observableArray([]);
self.query = ko.observable(''),
initialPlaces.forEach(function(placeLocation) {
self.placeList.push( new Place(placeLocation));
});
self.currentPlace = ko.observable( this.placeList()[0]);
};
ko.applyBindings(ViewModel);
data:
var initialPlaces = [
{"city":"R","lat":22,"lng":-102},
{"city":"T","lat":23,"lng":-110},
{"city":"P","lat":18,"lng":-92},
{"city":"F","lat":25,"lng":-102},
];
I already try this links Link1 Link2 and another ones but nothing... I'm a noob on Javascript and knockout (no more than 2 weeks in to it).
Every time I try any example my list goes blank and nothing is been displayed.
Could you please let me know where can a I find information on how to solve this issue or could you please help with any comment.
Thanks
Upvotes: 0
Views: 1908
Reputation: 35253
There are some issues with your code.
with
binding creates a new binding context. Which means, knockout will look for placeList
property inside currentPlace
object since you have that nested inside the with
binding.:
after with
in your binding (with currentPlace
)ko.applyBindings
, not a function. You can either create an object literal as ViewModel. Or create a function an then use the new
operator to create an object. You are using the latter. (Difference b/n object literal and using new
operator on a constructor function)I'm not sure what currentPlace
is supposed to do since you want to filter the array based on city
. You can create a computed
property like this which will filter
the array based on query
:
var initialPlaces = [{
"city": "London",
"lat": 22,
"lng": -102
}, {
"city": "New York",
"lat": 23,
"lng": -110
}, {
"city": "New Delhi",
"lat": 18,
"lng": -92
}];
var Place = function(data) {
this.city = ko.observable(data.city);
this.lat = ko.observable(data.lat);
this.lng = ko.observable(data.lng);
};
var ViewModel = function() {
var self = this;
self.placeList = ko.observableArray([]);
self.query = ko.observable('');
initialPlaces.forEach(function(placeLocation) {
self.placeList.push(new Place(placeLocation));
});
// everytime query/placeList changes, this gets computed again
self.filteredPlaces = ko.computed(function() {
if (!self.query()) {
return self.placeList();
} else {
return self.placeList()
.filter(place => place.city().toLowerCase().indexOf(self.query().toLowerCase()) > -1);
}
});
};
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<input type="text" data-bind="value: query, valueUpdate: 'keyup'" placeholder="Search...">
<div data-bind="foreach:filteredPlaces">
<span data-bind="text:city"></span><br>
</div>
Click on Run code snippet
to test it out. Here's a fiddle if you want to play around with it.
Upvotes: 6