Reputation: 214
I'm trying to implement the search filter in my web app. I read some good articles and i found some good Jsfiddles.
I want to search by TypeName
and show the row with that typename.
I implemented it in my model but i get and error when i search:
main.js:48 Uncaught TypeError: item.TypeName is not a function
also the screen error
My index.html:
<div class="form">
<div class="form-group">
<input type="search" class="form-control" data-bind="textInput: query" autocomplete="off" />
</div>
</div>
<div id="tab1" class="col s12">
<ul class="collapsible" data-collapsible="accordion" data-bind="foreach:brickInfos">
<li data-bind="with: value">
<div class="collapsible-header">
<i class="material-icons">view_stream</i>
<p class="blue-text" data-bind="text: TypeName"></p>
</div>
</li>
</ul>
</div>
My model :
function ViewModel() {
var self = this;
self.brickInfos = ko.observableArray([]);
db.query("BrickInfos/docs").then(function(result) {
var data = result;
console.log(data);
self.brickInfos(data.rows);
});
self.query = ko.observable("");
self.filteredBrickInfos = ko.computed(function () {
var filter = self.query().toLowerCase();
if (!filter) {
return self.brickInfos();
} else {
return ko.utils.arrayFilter(self.brickInfos(), function (item) {
return item.data.TypeName().toLowerCase().indexOf(filter) !== -1;
});
}
});
}
var db = new PouchDB('http://localhost:5984/helloworld');
var vm = new ViewModel();
ko.applyBindings(vm);
This is how my data looks: Json data on console
Any good advice how i should structure my code is always welcome, cuz i'm new in KnockoutJS. Thank you
I posted the JSON here:
{
"BrickInfos": {
"BrickInfos": [
{
"Properties": {
"Properties": [
]
},
"Implements": {
"Interfaces": [
{
"TypeName": "soemtypename"
},
{
"TypeName": "soemtypename2"
}
]
},
"Name": "AccessBareBoneApp",
"Description": "",
"TypeName": "soemtypename",
"AssemblyName": "string other safasgfas",
"Obsolete": true
},
{
"Properties": {
"Properties": [
{
"Name": "file",
"Description": "asfasf",
"ValidationType": 12,
"Converter": 12,
"EnumTypeName": "string1"
}
]
},
"Implements": {
"Interfaces": [
{
"TypeName": "soemtypename"
},
{
"TypeName": "soemtypename"
}
]
},
"Name": "File2",
"Description": "asfasfas",
"TypeName": "soemtypename",
"AssemblyName": "string other safasgfas",
"Obsolete": false
}
]
}
}
Upvotes: 0
Views: 1708
Reputation: 6045
You are getting item.TypeName
undefined because inside computed you seem to access typeName with ()
notation which is not observable .
Usually we un-wrap a observable using ()
which basically reads it's content .
viewModel :
var self = this;
self.brickInfos = ko.observableArray([]);
self.brickInfos(json.BrickInfos);
self.query = ko.observable("");
self.filteredData = ko.computed(function() {
var filter = self.query().toLowerCase();
if (!filter) {
return ;
} else {
return ko.utils.arrayFilter(self.brickInfos(), function(item) {
return item.TypeName.toLowerCase().indexOf(filter) !== -1;
});
}
});
}
var vm = new ViewModel();
ko.applyBindings(vm);
I have modified few stuff, you can see the working sample
var json = {
"BrickInfos": [{
"Properties": {
"Properties": [
]
},
"Implements": {
"Interfaces": [{
"TypeName": "soemtypename"
}, {
"TypeName": "soemtypename2"
}]
},
"Name": "AccessBareBoneApp",
"Description": "",
"TypeName": "soemtypename",
"AssemblyName": "string other safasgfas",
"Obsolete": true
}, {
"Properties": {
"Properties": [{
"Name": "file",
"Description": "asfasf",
"ValidationType": 12,
"Converter": 12,
"EnumTypeName": "string1"
}]
},
"Implements": {
"Interfaces": [{
"TypeName": "soemtypename"
}, {
"TypeName": "soemtypename"
}]
},
"Name": "File2",
"Description": "asfasfas",
"TypeName": "soemtypenameTest",
"AssemblyName": "string other safasgfas",
"Obsolete": false
}]
}
function ViewModel() {
var self = this;
self.brickInfos = ko.observableArray([]);
self.brickInfos(json.BrickInfos);
self.query = ko.observable("");
self.filteredData = ko.computed(function() {
var filter = self.query().toLowerCase();
if (!filter) {
return self.brickInfos();
} else {
return ko.utils.arrayFilter(self.brickInfos(), function(item) {
return item.TypeName.toLowerCase().indexOf(filter) !== -1;
});
}
});
}
var vm = new ViewModel();
ko.applyBindings(vm);
body {
font-family: arial;
font-size: 14px;
}
.liveExample {
padding: 1em;
background-color: #EEEEDD;
border: 1px solid #CCC;
max-width: 655px;
}
.liveExample input {
font-family: Arial;
}
.liveExample b {
font-weight: bold;
}
.liveExample p {
margin-top: 0.9em;
margin-bottom: 0.9em;
}
.liveExample select[multiple] {
width: 100%;
height: 8em;
}
.liveExample h2 {
margin-top: 0.4em;
font-weight: bold;
font-size: 1.2em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="form">
<div class="form-group">
<input type="search" class="form-control" data-bind="textInput: query" autocomplete="off" />
</div>
</div>
<div id="tab1" class="col s12">
<ul class="collapsible" data-collapsible="accordion" data-bind="foreach:filteredData">
<li>
<div class="collapsible-header">
<i class="material-icons">view_stream</i>
<p class="blue-text" data-bind="text: TypeName"></p><br>
</div>
</li>
</ul>
</div>
Upvotes: 1