meteor not printing any data - javascript

I have the following application and when I render data I am getting null or no data for the {{video}} tag even though data exists in the collection Can anyone help me find the mistake
routes.js
Router.route('/videos/:id', function () {
var item = Videos.find({_id: this.params._id});
this.render('VideoItem', { data:item});
});
video.html
<template name="VideoItem">
<div class="container">
<h3> Video Information</h3>
{{video}}
</div>
</template>
video object when Videos.find().fetch()
_id: "FEXm65hwZ9QWXFSY8"
created_at: Mon May 18 2015 14:22:59 GMT+0200 (CEST)
duration: 10000
video: "temp"
videourl: "http://google.com"
__proto__: Object

find returns a cursor. That would work if you were iterating over a set of videos with #each. In your case you want a specific video so you'd need to use findOne like this:
Router.route('/videos/:_id', function () {
this.render('VideoItem', {
data: function () {
return Videos.findOne(this.params._id);
}
});
});

Related

Polymer DOM update after viewport refresh

I've been trying to work this out but sofar have been unable to find an answer. My Polymer element loads a base template JSON file, which is then run through a dom-repeat to create a basic HTML page.
Then another JSON text-file is loaded, which completes the various areas of the HTML with a JS function.
Upon button-click form child, a function is run that triggers the loading of another JSON file that adds additional info. This all works fine.
But when I go out of the page and back in it, it has remembered all my settings but does not display things correctly. It displays the translatedText well and the html code is there, but it does not complete the html code for the originalText.
It seems to want to load the last JSON file before the DOM is properly rendered. So I want it to refresh the whole DOM, but how do I do this?
My MWE:
<template>
<iron-ajax
auto
url="basetext.json"
handle-as="json"
last-response="{{baseText}}"></iron-ajax>
<div class="textcontent">
<template is="dom-repeat" items="{{baseText.lines}}" as="line">
<div class="lineblock">
<div class="line" id="line{{line.lineid}}" inner-h-t-m-l="{{line.linetext}}"></div>
<template is="dom-if" if="[[extraShowEnabled]]">
<div class="linepi" id='linepi{{line.lineid}}' inner-h-t-m-l="{{line.linetext}}"></div>
</template>
</div>
</template>
</div>
<template is="dom-if" if="[[extraLoadEnabled]]">
<iron-ajax
auto
url="originaltext.json"
handle-as="json"
last-response="{{originalText}}"></iron-ajax>
</template>
<iron-ajax
auto
url="translatedtext.json"
handle-as="json"
last-response="{{translatedText}}"></iron-ajax>
</template>
<script>
Polymer({
is: 'text-page',
properties: {
translatedText: Object,
originalText: Object,
extraShowEnabled: {
type: Boolean,
value: false
},
extraLoadEnabled: {
type: Boolean,
value: false
},
showViewer: {
type: String,
value: "none"
}
},
observers: [
'setView(showViewer)',
' _computeSegments(translatedText,".line")',
' _computeSegments(originalText,".linepi")'
],
ready: function() {
this.addEventListener('eventFromChild', this.changeView);
},
changeView: function(event) {
this.showViewer = event.detail.selectedView;
},
setView: function(showViewer) {
\\ first some code here to reset all css.
if (showViewer === "none") {
this.extraShowEnabled = false;
this.extraLoadEnabled = false;
}
if (showViewer === "sidebyside") {
this.extraShowEnabled = true;
this.extraLoadEnabled = true;
this._computeSegments(this.originalText,".linepi");
this._addSideBySideCode();
}
},
_computeSegments: function(inputText,linetype) {
if (inputText) {
Array.from(this.querySelectorAll(linetype+" sc-segment")).forEach(item => item.innerHTML = inputText.segments[item.id]);
}
},
_addSideBySideCode: function() {
\\ this function just adds some css.
},
});
</script>
I think You should try to use a compute function result as a dom-repeat item source, something like this:
<template is="dom-repeat" items="{{itmesByParamsCompute(baseText, originalText, translatedText, extraloadEnabled, ...)}}" as="line">
Add as many params as You need to recompute on. Then that compute function should return a valid source anytime at least one of the paras changes.
Also keep in mind, that if any of these params will become undefined that compute function might be ignored completely. Work around for this is making this opposite way - one property which is modified from manny observers, something like this:
properties: {
items_to_use: {
type: Array,
value: []
},
translatedText: {
type: Object,
observer: 'updateItemsToUse'
},
originalText: {
type: Object,
observer: 'updateItemsToUse'
}
},
updateItemsToUse: function (data) {
let updatedArray = this.someMixFixFunction(this.item_to_use, data);
this.set('items_to_use', updatedArray);
},
someMixFixFunction: function (old_array, data_to_apply) {
// do some merging or what ever You need here, for example
let updatedArray = old_array.concat(data_to_apply);
return updatedArray;
}

DOM is not getting updated on updating VueJS data object

I have a VueJS data object in JS script. The JS script is linked at end of the page. So first HTML will is getting rendered. Then VueJS data object will be initialised. After initialising data object, DOM is getting updated perfectly. But after this, on updating the VueJS data object in success function of this.$http(), DOM is not getting updated. I have read documentation on reactivity and Common Beginner Gotchas. But I didn't get solution. If anyone knows the answer, it will be appreciated.
Here is my code.
index.html
<body>
....
{{ind_case.comments.length}}
<div class="comment_item" v-for="comment in ind_case.comments">
</div>
....
<script src="index.js"></script>
</body>
index.js
new Vue({
....
data: {
ind_case: {}
},
created: function () {
this.getCaseDetails();
},
methods: {
getCaseDetails: function () {
this.ind_case = {
"case_id": 16
}
this.getCaseComments(this.ind_case.case_id);
},
getCaseComments: function(case_id){
this.$http.get('/api/comments/' + case_id)
.then((response) => {
console.log(response.data); // Output: [{cmnt: "blah"}, {cmnt: "blah blah"}]
// Here i want add these comments in ind_case data object as ind_case.comments
// I have tried this
// this.$set(this.ind_case, 'comments', response.data);
// console.log(this.ind_case.comments); // Output: [Array[2], __ob__: Di]
}, (response) => {})
}
}
....
})
As seen in code, I can get comments in DOM. But I have to use .comments[0].length instead of .comments.length. And that's not the way to code.
EDIT
As suggested in below comment, I have tried this. But still same output (i.e, [Array[2], __ob__: Di]). And also one more thing. If I choose this option, I have to pre-define data object. But my requirement is run time creation/addition of data.
first thing, data should be a function and return {ind_case: {comments: []}}
i would recammend you make new object this way for ajax response
(response) => {
var data = response.data.map(o => getUwantProps(o));
this.ind_case.comments = data;
}

polymerfire/firebase-query transaction complete event

Very new to Polymer and Polymerfire. I couldn't find an answer here so hoping I can get help here. The basic question I have is "how do I work with the data that polymerfire/firebase-query sends?" Note I'm using polymerfire version 0.9.4, and polymer is version 1.4.0.
I can load my data from Firebase no problem using Firebase query, however some of the values are raw numbers that I need to convert to user friendly information. For example I have time stored in ms that I want to convert to a date, and a numeric field that indicates the "type" of data that is stored and I want to show an icon for it, not just a raw number. I figured my best option would be to use the transactions-complete promise or an observer. Both fire but neither seems to give me access to the data. The Observer's newData is an empty array, and transactions-complete.. well I don't really know what to do with that when the promise fires. Below is my relevant code. I also tried using notify: true, but I seem to not be grasping the concept correctly.
<firebase-query
id="query"
app-name="data"
path="/dataPath"
transactions-complete="transactionCompleted"
data="{{data}}">
</firebase-query>
<template is="dom-repeat" items="{{data}}">
<div class="card">
<div>Title: <span>{{item.title}}</span></div>
<div>Date Created: <span>{{item.dateCreated}})</span></div>
<div>Date Modified: <span>{{item.dateModified}}</span></div>
<div>Status: <span>{{item.status}}</span></div>
</div>
</template>
Polymer({
is: 'my-view1',
properties: {
data: {
notify: true,
type: Object,
observer: 'dataChanged'
}
},
dataChanged: function (newData, oldData) {
console.log(newData[0]);
// do something when the query returns values?
},
transactionCompleted: new Promise(function(resolve, reject) {
// how can I access "data" here?
})`
I wound up going another way entirely, which seemed to be a cleaner approach to what I was doing anyways. I broke it down into separate components. This way when the detail component was loaded, the ready function would allow me to adjust the data before it got displayed:
list.html:
<firebase-query
id="query"
app-name="data"
path="/dataPath"
data="{{data}}">
</firebase-query>
<template is="dom-repeat" items="{{data}}">
<my-details dataItem={{item}}></my-details>
</template>
details.html
<template>
<div id="details">
<paper-card heading="{{item.title}}">
<div class="card-content">
<span id="description">{{item.description}}</span><br/><br/>
<div class="details">Date Created: <span id="dateCreated">{{item.dateCreated}}</span><br/></div>
<div class="details">Last Modified: <span id="dateModified">{{item.dateModified}}</span><br/></div>
<div class="status"><span id="status">{{item.status}}</span><br/></div>
</div>
</paper-card>
</template>
Then in the javascript ready function I can intercept and adjust the data accordingly:
Polymer({
is: 'my-details',
properties: {
item: {
notify: true,
},
},
ready: function() {
this.$.dateModified.textContent = this.getDate(this.item.dateModified);
this.$.dateCreated.textContent = this.getDate(this.item.dateCreated);
this.$.status.textContent = this.getStatus(this.item.status);
},
Try the following changes:
Take out the transactions-completed attribute - it is only relevant when the query is updating data to Firebase
Change the dom-repeat template to get it's items attribute from convertedData - this allows you to do the data conversions to## Heading ## the results of the firebase-query
<firebase-query
id="query"
app-name="data"
path="/dataPath"
data="{{data}}">
</firebase-query>
<template is="dom-repeat" items="{{convertedData}}">
<div class="card">
<div>Title: <span>{{item.title}}</span></div>
<div>Date Created: <span>{{item.dateCreated}})</span></div>
<div>Date Modified: <span>{{item.dateModified}}</span></div>
<div>Status: <span>{{item.status}}</span></div>
</div>
</template>
Add a convertedData property to do your data conversions from data which has the raw data
Change the observer syntax as per the example. This sets up the observer to to observe for changes to deep property values which results in the observer method being fired - see: https://www.polymer-project.org/1.0/docs/devguide/observers#deep-observation
In the observer method you can populate the convertedData object from the data object which should then render the content
Polymer({
is: 'my-view1',
properties: {
data: {
notify: true,
type: Object
},
convertedData: {
notify: true,
type: Object
}
},
// observer syntax to monitor for deep changes on "data"
observers: [
'dataChanged(data.*)'
]
dataChanged: function (newData, oldData) {
console.log(newData);
// convert the "newData" object to the "convertedData" object
}
}

FindRecord with Ember and MongoDB

I have been looking on the web for an answer to this but I have not been able to find one, maybe I am not asking the right questions but here it goes.
So Im building a CRUD webapp using express, mongodb and ember cli, so far I can save data to my mongodb database (/events/new) and display my events (events/all) however I seem to be stuck when accessing an individual event my ideal URL will be /events/:eventname...
I know i'm getting the right result from the server, and I am getting ONLY ONE, however in the ember console, my model shows all my records, plus I cant seem to render the actual content from my model to the screen. IF I happen to go localhost:300/event/XXXX my ember console shows two records the one I want and some sort of dummy one having XXXX as the ID and the rest of the fields are undefined... Do i need to create a new route to look for the single record? or is there a way to use the same route I defined to look for all my records in events/all ? How do i get the data displayed on the screen ? Why do i see all my records when I access /events/eventname ?
Am I following best practices here ?
Express:
app.get('/api/events', function(req,res) {
eventsModel.find({},function(err,docs) {
if(err) {
res.send({error:err});
}
else {
// we only want to display the current events,
// so we filter throught them and return
// only the current ones
var current = [];
var today = new Date();
var tomorrow = today.setDate(today.getDate() - 1);
docs.forEach(function(item){
if(item.date >= tomorrow){
// console.log('new');
current.push(item);
}
});
res.send({events:current});
console.log('/api/events');
}
});
});
app.get('/api/events/:name', function(req, res){
console.log(req.url);
console.log('/api/events/event');
eventsModel.findOne({name: req.params.name},function(err,docs) {
if(err) {
res.send({error:err});
}
else{
res.send({event:docs});
}
});
});
Ember Router.js
Router.map(function() {
this.route('events', function() {
this.route('new');
this.route('update');
this.route('all');
this.route('event', { path: ':name' });
});
});
Ember events.event Routes
export default Ember.Route.extend({
model: function(params) {
this.store.find('event', params.name);
}
});
Ember events.all Template
{{#if model}}
{{#each model as |event| }}
<h2>{{#link-to 'events.event' event.name}}{{event.name}}{{/link-to}}</h2>
<p>{{event.date}}</p>
<p>{{event.location}}</p>
<p>{{event.address}}</p>
<a href={{event.url}}>Read More</a>
{{/each}}
{{else}}
Ember events.event Template
{{#each model as |item|}}
{{item.name}}
{{/each}}
{{outlet}}
My server response when going to /events/eventname is:
{ _id: 55d317d23281dfb23e9ecaa8,
url: 'http://gmail.com',
timestamp: Tue Aug 18 2015 07:32:34 GMT-0400 (EDT),
description: 'Another Address',
address: '123 Street',
long: 34.234,
lat: 12.123,
zip: 'h4t3y5',
city: 'Here',
location: 'Somewhere',
date: Mon Aug 31 2015 20:00:00 GMT-0400 (EDT),
name: 'Two Words',
__v: 0 }
The data is accurate and it changes depending on the post I click on.
Thanks for your help!
Assuming that you're using the RESTAdapter, your server response is in the wrong format. You can read about the format it expects here, but your response should look something like this:
{
"event": {
"id": "55d317d23281dfb23e9ecaa8",
"timestamp": "Tue Aug 18 2015 07:32:34 GMT-0400 (EDT)",
...
}
}

AngularJS Nested Object Array Pathway

I have a factory, which goes into a controller, and I am trying to get data from that display on an HTML page. I am having trouble specifying an Object's pathway however.
My Factory:
app.factory('APIMethodService', function() {
var Head = "api.example.com";
return {
apis:
[{
accounts: [
{
v1: [
{
uri: Head+"/v1/accounts/",
item1: "AccountNumber",
item2: "MoneyInAccount"
}],
v2: [
{
uri: Head+"/v2/accounts/",
item1: "AccountNumber",
item2: "MoneyInAccount"
}]
}
],
customers: [
{
v1: [
{
uri: Head+"/v1/customers/",
item1: "CustomerName",
item2: "CustomerID",
item3: "CustomerEmail"
}]
}
]
}]
};
});
My Controller:
app.controller('APIController', function($scope, APIMethodService) {
$scope.title = "API";
$scope.apiList = APIMethodService;
$scope.accountList = $scope.apiList.accounts.v1;
$scope.accountList2 = $scope.apiList[0][0];
});
My HTML
<div ng-controller="APIController">
<div id="api" class="row">
<div class="col-xs-12">
<div class="row" style="font-size:20px">
{{title}} Page!
<table class="table table-striped">
<tr ng-repeat="api in apiList | orderBy:'uri' | filter:search">
<td>{{api.uri}}</td>
<td>{{api.item1}}</td>
<td>{{api.item2}}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
The errors I get are in regards to the Controller trying to parse out the individual objects I wish to grab, like accounts or customers, and then any version v#, they may have.
So it will say something such as
TypeError: Cannot read property 'v1' of undefined
I just need some help specifying the proper pathways into my factory service.
You have a few problems. First, you are referring to the object returned from the factory incorrectly. APIMethodService is the factory that you're injecting, so you need to first reference the object that that factory is returning like this:
APIMethodService.apis
This will give you your entire JSON object.
From there, the rest of your object is made up of arrays of objects, so referring to 'v1' won't do you any good. You need to specify an index instead. If you want v1, you'll need:
APIMethodService.apis[0].accounts[0].v1
This will give you the v1 array, which again is an array of objects.
Customers would be:
APIMethodService.apis[0].customers[0].v1
The first problem you have is that the factory returns an object with a single property called apis. So basically this $scope.apiList.accounts.v1 should be $scope.apiList.apis.accounts.v1. Bu that's not all as this won't either work since dotting(.) into apis is an array you'd have to use the index. In this case it would be $scope.apiList.apis[0] and then you could .accounts[0].v1 which is also an array containing a single object.
Now if you can I would suggest to you that you'd change how you represent this data structure.
This is how you could do it.
app.factory('APIMethodService', function() {
var Head = "api.example.com";
return {
accounts: {
v1: {
uri: Head+"/v1/accounts/",
items: ["AccountNumber","MoneyInAccount"]
},
v2: {
... // skipped for brevity
}
},
customer: {
... // code skipped for brevity
}
};
});
And then it's just a matter of dotting into your APIMethodService-object like APIMethodService.accounts.v1.items[0] if you want the AccountNumber method name.
Constructing your url could then be done like this.
var baseUrl = APIMethodService.accounts.v1.uri; // 'api.example.com'
var url = baseUrl + APIMethodService.accounts.v1.items[0]; // 'AccountNumber'
// url = "api.example.com/v1/accounts/AccountNumber"
Again, this is one way you could do it but this can be further enhanced upon. The examples I provided are simply for demo purposes and this is not in any way the only way to do it.
Expanding upon recieved comments/questions your service (and data representation) could now look like this.
app.factory('APIMethodService', function() {
var Head = "api.example.com";
return {
accounts: {
v1: {
uri: Head+"/v1/accounts/",
items: [
{
name:'AccountNumber',
description:'Show the account number'
},
{
name:'AccountOwner',
description:'Show information about the owner of the account'
},
{
name:'MoneyInAccount',
description:'Show money in the Account'
}
]
},
v2: {
... // skipped for brevity
}
},
customer: {
... // code skipped for brevity
}
};
});
// Get descriptions
var accountNumberDescription = APIMethodService.accounts.v1.items[0].description; // 'Show the account number'
var accountOwnerDescription = APIMethodService.accounts.v1.items[1].description; // 'Show information about the owner of the account'
var moneyInAccountDescription = APIMethodService.accounts.v1.items[2].description; // 'Show money in the Account'
By using objects with properties like this it's alot easier to understand what you are trying to do. With arrays with indexes you'd have to know or take a look at the source to see what's going on. Here, someone viewing your code they can instantly understand that it is the description you are getting.

Categories

Resources