List.JS - Cannot read property 'childNodes' of undefined - javascript

I cannot seem to figure this out. I've already tried $(document).ready and still doesn't work for me. I've also tried making a for loop specifically for these two value names to save the results to a var and pass it in that way. I've also tried putting the input with the class and id with search inside of the parent div and outside. Essentially like it in the nav bar. Using list.js & knockout.js btw. Im getting my venues using an ajax request using foursquares api.
JS:
var options = {
valueNames: ['name', 'category']
};
var userList = new List('search', options);
HTML:
<body>
<nav>
<h1 class="formattedH1">Downtown SA,TX</h1>
<span>
<input type="search" placeholder="Search" class="search" id="search">
<input type="button" class="sort searchButton" value="List"></input>
</span>
</nav>
<div id="map" class="map"></div>
<div class="list">
<input type="search" placeholder="Search" class="search" id="search">
<h1>My Top 5</h1>
<!-- Square card -->
<div class="card" id="favViewModel" data-bind="foreach: favList">
<div class="expand">
<h2 class="venueName" data-bind="text:name"></h2>
</div>
<div class="cardSupport" data-bind="attr: {src: image()}">
</div>
<div class="cardSupport" data-bind="text:address">
</div>
<a data-bind="attr: {href: website()}">Website</a>
</div>
<h1>Foursquare Recommended</h1>
<div class="card" id="recViewModel" data-bind="foreach: recommendedSpotList ">
<div class="expand">
<h2 class="venueName" data-bind="text:name"></h2>
</div>
<div class="cardSupport" data-bind="text:location">
</div>
<div class="cardSupport" data-bind="text:category">
</div>
<div class="cardSupport" data-bind="text:rating">
</div>
</div>
<script src="js/tester123.js"></script>

I fixed the same problem with some comments on the github page of the project, just make sure to have the same names as the examples and it will work, everything must be in a <div> and the ul must have the class list
Like this
<div id="hacker-list">
<ul class="list"></ul>
</div>
Link: https://github.com/javve/list.js/issues/9

I found my answer browsing other similar projects, so simple now. Thought it might help someone in case they ran across this. It was that since I was making an ajax call I had to to place the call to ko.applybindings inside the ajax request. The binding was out of scope, if you think about it make's sense especially if your request fails. Why even attempt to still bind the values of the request. HTML as above, and for JS ajax request please see below:
JS:
$.ajax({
url: 'https://api.foursquare.com/v2/venues/explore',
dataType: 'json',
data: 'data',
async: true,
success: function(data) {
venues = data['response']['groups'][0]['items'];
//This is where I had to place the binding to get it to render properly.
ko.applyBindings(new recommendedViewModel(), document.getElementById('recViewModel'));
},
error: function() {
alert("An error occurred.");
}
});

"Hello World" example of this error.
Where?
https://listjs.com/api/#listClass
listClass String, default: "list" What is the class of the
list-container.
Case one (Missing list class):
/* error example */
var options = {
valueNames: [ 'name', 'born' ],
};
var userList = new List('users', options);
<!-- error example -->
<div id="users">
<input class="search" placeholder="Search" />
<button class="sort" data-sort="name">
Sort by name
</button>
<ul data-missing-list-class class="">
<li>
<h3 class="name">John</h3>
<p class="born">1986</p>
</li>
</ul>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/list.js/1.5.0/list.min.js"></script>
Case two (custom listClass missing):
I declare listClass to be no_such_class. The code trying to read childNodes of undefined.
/* error example */
var options = {
valueNames: [ 'name', 'born' ],
listClass: "no_such_class" /* the error */
};
var userList = new List('users', options);
<!-- error example -->
<div id="users">
<input class="search" placeholder="Search" />
<button class="sort" data-sort="name">
Sort by name
</button>
<ul class="list">
<li>
<h3 class="name">No such class</h3>
<p class="born">1986</p>
</li>
</ul>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/list.js/1.5.0/list.min.js"></script>
**the error will not throw under stackoverflow snippet
Extra
Remember to not confuse between:
id or element
Id the element in which the list area should be initialized. OR the
actual element itself.
new List(id/element, options, values);
VS:
listClass
What is the class of the list-container?

Related

List.js - clickable links

My List.js implementation is creating what appear to be links but they're un-clickable. In the image I attached everything appears correct, however the link doesn't work even though when you hover it even underlines like a normal link would. What am I missing here?
I read somewhere that <li> items cannot be assigned href tags? If that is true then how does one get around that little issue?
Javascript:
<script>
var options = {
valueNames: [ 'title', 'description', 'lat', 'lng', 'user_sub', 'location', 'imageurl', 'final_url' ],
item: '<li id="my-list"><h3 class="title"></h3><p class="description"></p><p class="location"></p><p class="user_sub"></p><a class="final_url"></a></li>'
};
var values = JSON.parse('{{ jsonout|safe }}');
var userList = new List('places', options, values);
</script>
HTML:
<div id="places" class="container">
<input class="search" placeholder="Search" />
<button class="Find" data-sort="title">
Search
</button>
<button id="click_me" class="sort" data-sort="location">
Sort by State
</button>
<button id="click_me" class="sort" data-sort="title">
Sort by Name
</button>
<ul class="list"></ul>
</div>

AngularJS advice on how to fix a bug when pushing two of the same strings into the array

I'm having trouble trying to figure out how to fix a bug that happens when I try to push the same string as added previously to the array. It gets stuck and will not allow the app to post another string.
How do I make sure that your repeat doesn't get stuck when there two of the same values in the array?
Bug Example Screenshot
--> Bug happens when I try to push "1"into the array again after a "1" is already posted.
HTML Code
<body>
<div data-ng-controller="appController" class="container">
<div class="row">
<form>
<label for = "status"> Status: </label>
<input data-ng-model = "input_data" type="text" id="status"/>
<button data-ng-click="add_data()"> OK </button>
<ul class = "list-group">
<li class="list-group-item" data-ng-repeat="x in array_data">
{{x}}
<button data-ng-click = "remove_data($index)">DEL</button>
</li>
</ul>
</form>
</div>
</div>
<script src="framework/js/jquery.min.js"></script>
<!-- All Bootstrap plug-ins file -->
<script src="framework/js/bootstrap.min.js"></script>
<!-- Basic AngularJS -->
<script src="framework/js/angular.min.js"></script>
<!-- Your Controller -->
<script src="framework/js/appstatpost.js"></script>
</body>
AngularJS code
var app = angular.module("myApp", []);
app.controller("appController", function ($scope) {
$scope.array_data = [];
$scope.add_data = function () {
$scope.array_data.push($scope.input_data);
};
$scope.remove_data = function (index) {
$scope.array_data.splice(index, 1);
};
});
You could use track by $index, example:
<li class="list-group-item" data-ng-repeat="x in array_data track by $index">
AngularJS tries by default to find a key in your array to index by. Normally this works well, but if you have duplicates then you have to tell AngularJS to make a new index, in this case, $index.

Mustache.js is adding text instead of html

It's my first time when I use mustache.js and need some help, please.
Doing a html template builder and I am trying to grab data from JSON and HTML files, than show them into my page.
So I am using this script to get Default theme from JSON than to get the HTML:
$.getJSON('templates.json', function(json){
$.each(json, function(theme, val){
if(theme == 'Default'){
template.load('templates/'+val.url+'/template.html', function(response, status, xhr){
$(this).html(Mustache.render($(this).html(), {
tabs:val.tabs
}));
});
}
});
});
JSON:
{
"Default" : {
"url":"default",
"logo": "YOUR LOGO HERE",
"phone": "+1234567890",
"tabs": [
"About Us",
"Delivery",
"Payment",
"Shipping",
"Contact Us"
]
}
}
HTML:
{{#tabs.length}}
<div id="tabs">
{{#tabs}}
<input class="state" type="radio" title="tab1" name="tabs-state" id="tab1" checked />
{{/tabs}}
<div class="tabs flex-tabs">
{{#tabs}}
<label for="tab1" id="tab1-label" class="tab">{{.}}</label>
{{/tabs}}
{{#tabs}}
<div id="tab1-panel" class="panel active">[[{{.}}]]</div>
{{#tabs}}
</div>
</div>
{{/tabs.length}}
I just can't display the tabs. First time I tried with javascript to convert json into html, but Mustache was showing text instead of html. Now I am trying with conditions in html with no luck.
I also need to add numbers to each item, eg: "tab1", "tab2".. - is this {{#index}} good for that?
How can I add checked only for first items?
Also not sure if {{.}} this is displaying the name of my tab..
You've almost got this nailed, although have slightly misunderstood how to write the mustacheJS view. It's even simpler than you thought! See below. I've simplified the example, so you understand the concept.
Some explanation for below:
{{#Default}}{/Default}} represents looping over an object literal
{{#tabs}}{{/tabs}} presents looping over the object that exists within {{#Defaults}}.
{{.}} displays the entire contents of the object. If this was a complex object, it would be rendered as [object][object]. If you ever encounter this, you must name the object explicitly in your view.
<div class="tabs">
{{#Default}}
{{#tabs}}
<input class="state" type="radio" title="Tab1" name="tabs-state" checked/>
<div class=tabs flex-tabs>
{{.}}
</div>
{{/tabs}}
{{/Default}}
</div>
View Produced
<div class="tabs">
<div class=tabs flex-tabs>
About Us
</div>
<div class=tabs flex-tabs>
Delivery
</div>
<div class=tabs flex-tabs>
Payment
</div>
<div class=tabs flex-tabs>
Shipping
</div>
<div class=tabs flex-tabs>
Contact Us
</div>
</div>

Dynamically adding items to HTML list

I'm currently building a wizard in asp.net MVC 5 application using knockout. On one of the steps, I need to add items to an html list. that is, text is enter into a textbox and you click the added button, the text is added to the list.
My template:
<script type="text/html" id="addProduct">
<li class="dd-item bordered-inverse animated fadeInDown">
<div class="dd-handle dd-nodrag">
<div class="checkbox">
<label>
<a data-bind="attr: { 'href': '#' }" class='btn btn-xs icon-only success'><i class="fa fa-trash-o"></i></a>
<label data-bind="text: Name, uniqueName: true"></label>
</label>
</div>
</div>
</li>
</script>
<div class="row">
<div class="col-md-6">
<div id="newProduct" class="dd">
<ol class="dd-list" data-bind="template: { name: 'addProduct', foreach: Model.Step1.ProductServices }"></ol>
</div>
</div>
</div>
input textbox:
#Html.TextBoxFor(model => model.Step1.ProductService, new { data_bind = "value: Model.Step1.ProductService")
<button type="button" id="addservice" data-bind="event:{ click: AddProduct }">Add Service/Product</button>
knockout add event:
self.AddProduct = function () {
self.Model.CurrentStep().ProductServices.push({ name: self.Model.CurrentStep().ProductService });
}
self.Model.CurrentStep().ProductServices is a List Product as just one property name.
The code above add an item to the html list and updates the UI, but self.Model.CurrentStep().ProductServices.length is always zero, meaning nothing was added to the Model itself.
Please how can I force it to update the self.Model.CurrentStep().ProductServices?
length is not a property of an observableArray. Check ProductServices().length instead.

Angular.js Error: Duplicates in a repeater are not allowed - Track by index doesn't work as intended

I am going through a tutorial on the Ionic Framework, which is using Angular JS to create a simple Todo app. It creates a new task by using .push() to append a new task object onto an array of task objects (code is below).
I am getting this error when I try add more than one task.
Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: task in tasks, Duplicate key: object:00C
http://errors.angularjs.org/1.2.4/ngRepeat/dupes?p0=task%20in%20tasks&p1=object%3A00C
I've tried using the solution as posted in this answer and this blog post, which suggest adding track by $index, but it doesn't work properly for me...
It does get rid of the error, but then when I add a new task it updates all of the objects in the array with that new task! And in my list of tasks within the ng-repeat block I can see each task is now the same as the one I just added.
What am I doing wrong here? Is it something to do with the objects that I'm pushing onto the array? I am new to Angular.js so perhaps I am missing something simple yet crucial?
Here is my HTML:
<body ng-app="todo" ng-controller="TodoCtrl">
<side-menus>
<!-- Center content -->
<pane side-menu-content>
<header class="bar bar-header bar-dark">
<h1 class="title">Todo</h1>
<!-- New Task button-->
<button class="button button-icon" ng-click="editTasks()">
<i class="icon ion-edit"></i>
</button>
<button class="button button-icon" ng-click="newTask()">
<i class="icon ion-compose"></i>
</button>
</header>
<content has-header="true">
<!-- our list and list items -->
<list>
<item ng-repeat="task in tasks track by $index">
{{task.title}}
</item>
</list>
</content>
</pane>
<!-- Left menu -->
<side-menu side="left">
<header class="bar bar-header bar-dark">
<h1 class="title">Projects</h1>
</header>
</side-menu>
<!-- Add a new task -->
<script id="new-task.html" type="text/ng-template">
<div class="modal">
<!-- Modal header bar -->
<header class="bar bar-header bar-secondary">
<h1 class="title">New Task</h1>
<button class="button button-clear button-positive" ng-click="closeNewTask()">Cancel</button>
</header>
<!-- Modal content area -->
<content has-header="true">
<form ng-submit="createTask(task)">
<div class="list">
<label class="item item-input">
<input type="text" placeholder="What do you need to do?" ng-model="task.title">
</label>
</div>
<div class="padding">
<button type="submit" class="button button-block button-positive">Create Task</button>
</div>
</form>
</content>
</div>
</script>
</side-menus>
</body>
And here is my JS:
angular.module('todo', ['ionic'])
.controller('TodoCtrl', function($scope, Modal) {
// No need for testing data anymore
$scope.tasks = [];
// Create and load the Modal
Modal.fromTemplateUrl('new-task.html', function(modal) {
$scope.taskModal = modal;
}, {
scope: $scope,
animation: 'slide-in-up'
});
// Called when the form is submitted
$scope.createTask = function(task) {
console.log('task', task);
$scope.tasks.push(task);
console.log('$scope.tasks', $scope.tasks);
$scope.taskModal.hide();
};
// Open our new task modal
$scope.newTask = function() {
$scope.taskModal.show();
};
// Close the new task modal
$scope.closeNewTask = function() {
$scope.taskModal.hide();
};
});
The problem looks like you are not creating independent task instances. It appears that your modal is binding to a single task instance and attempting to add the same exact reference each time. Try something like the following.
In your JS:
// Open our new task modal
$scope.newTask = function() {
$scope.editTask = {};
$scope.taskModal.show();
};
In your HTML:
<form ng-submit="createTask(editTask)">
<div class="list">
<label class="item item-input">
<input type="text" placeholder="What do you need to do?" ng-model="editTask.title">
</label>
</div>
<div class="padding">
<button type="submit" class="button button-block button-positive">Create Task</button>
</div>
</form>
That creates a new editTask instance every time the newTask function is called and adds that new instance to the array. You should not need the track by $index code after those changes.

Categories