Knockout did not render template with my data - javascript

Stuck with javascipt's knockout library.
So, I want to implement simple forum. I have javascript file with two ajax requests, for topics and for posts. And I have html template.
function dealModel() {
var self = this;
self.board = ko.observableArray([]);
var res = [];
$.getJSON("http://someaddress/threads", function(data) {
$.each(data, function(i, thread) {
var js = jQuery.parseJSON(thread);
js.posts = ko.observableArray([]);
var postres = []
$.getJSON("http://someadress/posts/" + js.id, function(postdata) {
$.each(postdata, function(idx, post){
var jspost = jQuery.parseJSON(post);
postres.push(jspost);
})
})
js.posts(postres);
res.push(js);
})
self.board(res);
})
}
$(document).ready(function(){
ko.applyBindings(new dealModel());
});
var testdata = [{text : "text 1"} , {text : "text2"}]
This is my js code. It perfectly works with topics, but when I put my posts, my observable array "posts" already empty.
For test I created test array "testdata" (below), and pass in my observable array. And, javascript work perfectly.
Here is my template
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"></script>
<script type="text/javascript" src="ajaxknockout.js"></script>
</head>
<body>
<div class='board'>
<div class='threads' data-bind="foreach: board">
<p data-bind="text: title"></p>
<div class= "posts" data-bind="foreach: $data.posts">
<p data-bind="text: text"> </p>
</div>
</div>
</div>
</body>>
</html>
So, I think something bad with my posts JSON.
Here it is.
["{\"createTime\": \"Monday, 04. January 2016 05:53PM\",\"thread_id\": \"2\",\"text\": \"post 1\",\"id\": \"4\"}", "{\"createTime\": \"Monday, 04. January 2016 05:53PM\",\"thread_id\": \"2\",\"text\": \"post 2\",\"id\": \"5\"}", "{\"createTime\": \"Monday, 04. January 2016 05:53PM\",\"thread_id\": \"2\",\"text\": \"post 3\",\"id\": \"6\"}"]
SO, I have a question. Whats wrong with my code? Why knockout understand my testdata, but completly reject production data?

That's because this part of your first json request:
js.posts(postres);
executes ahead of callback from your second json request where you are pulling posts. You have to change that so the posts array is populated before doing js.posts(postres);, e.g like so:
$.getJSON("http://someadress/posts/" + js.id, function(postdata) {
$.each(postdata, function(idx, post){
var jspost = jQuery.parseJSON(post);
postres.push(jspost);
})
js.posts(postres);
})

Related

JQuery and Autocomplete Using a List (Python/Flask)

This has probably been asked before, but after searching for awhile I'm still a bit confused. I'm trying to make a flask app but I'm not too familiar with JQuery itself, but I would like to create an autocomplete widget in my html. However, instead of querying a database I'd like to just use a static list and a regex to get results. I used this as reference.
What I did was:
#app.route('/autocomplete', methods=['GET'])
def autocomplete():
search = request.args.get('q')
#query = db_session.query(Movie.title).filter(Movie.title.like('%' + str(search) + '%'))
#results = [mv[0] for mv in query.all()]
results = ['Beer', 'Wine', 'Soda', 'Juice', 'Water']
return jsonify(matching_results=results)
while keeping the rest of the code:
<head>
<link href="//code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css" rel="Stylesheet"></link>
<script src="//code.jquery.com/jquery-2.2.0.min.js"></script>
<script src="//code.jquery.com/ui/1.10.2/jquery-ui.js" ></script>
<script type="text/javascript">
$(function() {
$("#autocomplete").autocomplete({
source:function(request, response) {
$.getJSON("{{url_for('autocomplete')}}",{
q: request.term, // in flask, "q" will be the argument to look for using request.args
}, function(data) {
response(data.matching_results); // matching_results from jsonify
});
},
minLength: 2,
select: function(event, ui) {
console.log(ui.item.value); // not in your question, but might help later
}
});
})
</script>
</head>
<body>
<div>
<input name="autocomplete" type="text" id="autocomplete" class="form-control input-lg"/>
</div>
</body>
I haven't implemented a regex but I assumed if I typed anything with at least 2 characters I would get a dropdown of the list I wrote above. However, I get nothing. Any ideas on how I can get this autocomplete to work?

how to loop through json data based on single column value using angularjs in mvc

I need to display data from two tables which are associated with foreign key
using angularjs in mvc. I am able repeat question but my requirement is display question with 4 options i couldnt get the solution for this, am new to angularjs,I will be thankful if anyone can help me
> Controller code :
public JsonResult displayQuestion()
{
var result = from q in Db.questions
join a in Db.answers on q.Qid equals a.questionID
select new { q.QText, q.Qid, a.answer1 };
return Json(result, JsonRequestBehavior.AllowGet);
}
> angular view code:
<html>
<head>
<meta name="viewport" content="width=device-width" />
<script src="~/Scripts/angular.min.js"></script>
<script>
var myApp = angular.module("QuestionDisplayModule", [])
.controller("QuestionDisplayController", function ($scope,$http,$log) {
$http.get("displayQuestion").then(function(response)
{
$log.info(response);
$scope.questionsData = response.data;
})
})
</script>
<title>dispaly</title>
</head>
<body ng-app="QuestionDisplayModule">
<div ng-controller="QuestionDisplayController">
<div ng-repeat="q in questionsData">
<h6>{{q.QText}}</h6>
<p><input type="radio" name="answers" ng-repeat = "a in q.answer1" />{{a.answer1}}</p>
</div>
</div>
</body>
json data result:
[
{"QText":"result of 2+2","Qid":2,"answer1":"2"},
{"QText":"result of 2+2","Qid":2,"answer1":"4"},
{"QText":"result of 2+2","Qid":2,"answer1":"6"},
{"QText":"result of 2+2","Qid":2,"answer1":"8"}
]
view result: Link

Read Json and update template from mustache

I have a Index.html file, where I am using container class.
I have another html file with which contains mustache variables.
Here is the code which I am using,
Lets say this is a.html.
<script id="filtersOptions" type="text/html">
<ul class="checkboxCommonContent">
{{#data}}
<li>
<div>
<input type="checkbox" id="checkbox-1-1" class="regular-checkbox"><label for="checkbox-1-1"></label><span class="lblText">{{brand_name}}</span>
</div>
</li>
{{/data}}
</ul>
I have a json file, where the brand information something like this,
{
"brands":[
{
"brand_name":"Adidas",
"available_products":30
}
]
}
Through Javascript I am featching the Json data and trying to udapete the mustache tempalte but getting error.
Featchng information from js
loadFileForFilters: function(){
$.getJSON('js/json/brand.json', {}, function(data, textStatus, jqXHr) {
console.log(data);
var f = $("#filtersOptions").html();
$.get('files/sort_and_filter_lb.html', function(template, textStatus, jqXhr) {
var template = Mustache.render(f, {data: data});
//$(".container").html(template);
});
});
}
container - Is in side index.html.
The sort_and_filter_lb.html file have following code
<script id="filtersOptions" type="text/html"><ul class="checkboxCommonContent"> {{#data}} <li> <div> <input type="checkbox" id="checkbox-1-1" class="regular-checkbox"><label for="checkbox-1-1"></label><span class="lblText">{{brand_name}}</span> </div> </li> {{/data}} </ul> </script>
Can some one please guide me. Why I am not getting the data in the main template.
Edit,
Browsed some documentations MUSTACHE MANUAL , and demonstrations A Simple Mustache Demo , along with re-reading Question , for introduction into Mustache.js .
At first glance , appear that json object at brand.json does not have data property to correspond to {{#data}} ; see http://mustache.github.io/mustache.5.html#Sections at template and hash of {{#repo}}.
Not certain about necessity of second ajax call, i.e., $.get() ? Existing #filtersOptions (f) html could be modified , to reduce ajax call to first , $.getJSON() ?
Above portions not directly addressed here , though ajax pieces re-arranged to process their respective return values within .then() callback .
Changed <script> element at sort_and_filter_lb.html file to <div> , for jsfiddle to process .
Note, Not previously tried Mustache.js
Try
v2
html
<script id="filtersOptions" type="text/html">
<ul class="checkboxCommonContent"> {{#data}}
<li> <div> <input type="checkbox"
id="checkbox-1-1"
class="regular-checkbox" /> <label
for="checkbox-1-1"> </label><span class="lblText">{{brand_name}}</span> </div>
</li> {{/data}}
</ul>
</script>
<div class="process">
<button>Process Template</button>
</div>
<div id="container"></div>
js
$(function () {
$(".process button").on("click", function () {
var f = $('#filtersOptions').html();
var _data = {
"brands": {
"data": [{
"brand_name": "Adidas"
}, {
"available_products": 30
}]
}
};
var file = String('<div id=filtersOptions type=text/html>'
+'<ul class=checkboxCommonContent> {{#data}} <li>'
+'<div>'
+'<input type=checkbox id=checkbox-1-1 class=regular-checkbox>'
+'<label for=checkbox-1-1></label>'
+'<span class=lblText>{{brand_name}}</span>'
+'</div> </li> {{/data}} </ul> </div>');
var request1 = $.post("/echo/json/", {
json: JSON.stringify(_data)
}, function (data, textStatus, jqxhr) {
return data.brands;
});
var request2 = $.post("/echo/html/", {
html: file
}, function (data, textStatus, jqxhr) {
return data
});
$.when(request1, request2)
.then(function (a, b) {
console.log(a[0], b[0]);
var html = Mustache.render(b[0] /* or , `f` */, a[0].brands);
$('#container').html(html);
})
});
});
jsfiddle http://jsfiddle.net/guest271314/uhf73/
Your code appears a little messed up but close. If you want to render a template using an external file and external data, try something like this:
$.getJSON('js/json/brand.json', {}, function(data) {
// on success, request template
$.get('files/sort_and_filter_lb.html', function(template_string) {
// when we have both template and data, render it
var output = Mustache.render(template_string, {data: data});
$(".container").html(output);
});
});

Returns Data Issue in Meteor?

I need to know about the below shown Issue :
JS Code:
Template.main.helpers({
ItemName: function() {
var self = this;
console.log("helpers : " +self.fieldoptions);
return _.map(self.fieldoptions,function(p)
{
p.parent = self;
return p;
});
}
});
HTML Code :
{{#each ItemName}}
{{this.parent.fname}}
{{/each}}
The above Js return code doesn't show the html.So how to show the above return code in HTML.I didn't get any idea about this.So please help me?
Its not clear to me so I'll write what I think is happening. You should have at least 2 files on your meteor directory (the one created with meteor create)
template.main.html that if you are not using any router to make the template append to the body should look like
<head>
<title>My title</title>
</head>
<body>
{{> templateMain}}
</body>
<template name="templateMain">
{{#each ItemName}}
{{fname}}
{{/each}}
</template>
template.main.js with something around these lines
FieldNames = new Meteor.Collection('fieldname');
if( Meteor.isServer && FieldNames.find().count() === 0)
_.each(['one','two','three','four'], function(value, index){
FieldNames.insert({ fname : value, index : index });
});
if(Meteor.isClient){
Template.main.helpers({
ItemName: function() {
return FieldNames.find();
}
});
}
So what I think was happening was that you didn't include the template on the body.
Let me know if something is not clear.

AngularFire removes Firebase locations

I'm trying to create a collaborative story-making app, using Angular and Firebase. Follow this link to get an idea of where I'm headed so far. You click on the "plus" icon to show a textarea, and add to the parts that are already there. I'm sure there are many ways to improve what I've coded so far, but my specific problem right now relates to switching between stories.
I have another Firebase reference with two stories, and each of the stories has different parts. To create a way to switch between stories I tried the following:
html:
<!doctype html>
<html lang="en" ng-app = "StoryApp">
<head>
<script src="https://cdn.firebase.com/v0/firebase.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angularFire/0.1.0/angularfire.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div class="wrapper" ng-controller="WrapperCtrl">
<div class="nav">
<a ng-repeat="story in storyList" ng-click="switchStory(story.location)" href="#" id="{{story.identity}}" style="margin-left:0.5em;">{{story.title}} Button</a>
</div>
</br>
<div class="insideWrapper">
<span class="item" id="{{part.number}}" ng-repeat="part in parts" ng-controller="ItemCtrl">{{part.text}}
<span ng-click="show=!show" style="margin-left:0.25em;color:blue;cursor:pointer;">+(Add Part Here)</span>
<form ng-show="show" ng-submit="addItem()">
<textarea ng-model="itemText" placeholder="Your story"></textarea>
<br>
<button type="submit" class="submit-button" value="submit" ng-click="show=!show">add</button>
<button ng-click="show=!show">cancel</button>
</form>
</span>
</div>
</div>
</body>
javascript:
var gApp = angular.module('StoryApp', ['firebase']);
function WrapperCtrl($scope, angularFire){
var urlStories = 'https://allstory.firebaseio.com/stories';
$scope.storyList = angularFire(urlStories, $scope, 'storyList', {});
function getStory(url){
var urlParts = url;
$scope.parts = angularFire(urlParts, $scope, 'parts', []);
}
$scope.switchStory = function(location){
getStory(location);
};
getStory('https://allstory.firebaseio.com/stories/story1/parts');
}
function ItemCtrl($scope){
$('.wrapper').on('click', '.submit-button', function(event) {
var idNum = function() {
return event.target.parentNode.parentNode.id;
};
$scope.addItem = function(){
$scope.parts.splice(Number(idNum())+1, 0, {text:$scope.itemText, number:Number(idNum())+1});
$scope.itemText = '';
reNumber();
};
function reNumber() {
var i = Number(idNum())+2, len=$scope.parts.length;
for (; i < len; i++) {
$scope.parts[i].number = i;
}
}
});
}
The above code isn't working for me. When "Story 1" or "Story 2" are clicked in the view I expected that the view would change to reflect the change in Firebase reference location (url). However, rather than the appropriate parts of the respective story appearing, nothing appears, and the parts locations (e.g. https://allstory.firebaseio.com/stories/story1/parts) for both stories are removed from my Firebase reference. My problem may be similar to this one.
I need the parts for "Story 1" or "Story 2" to appear when clicked. What can I change in my code to make this work? Should I try an entirely different approach to switching between stories?
AngularFire retrieves data from Firebase asynchronously and returns a promise, not the actual data itself. Therefore, you have a bug in your code where you're assigning the promise to the scope variable but using it before the promise has been resolved.
I would fetch both stories first before allowing the user to switch between them. For example:
function WrapperCtrl($scope, angularFire) {
$scope.showStories = false;
var urlStories = 'https://allstory.firebaseio.com/stories';
angularFire(urlStories, $scope, 'storyList', {}).then(function() {
$scope.showStories = true;
});
$scope.switchStory = function(location) {
// var name = manipulate location to extract story number or name, like "story1".
$scope.parts = $scope.storyList[name]["parts"];
}
}

Categories