I'm trying to access info in an array created by meteor auto-form. The set in question is below.
PlayersSchema = new SimpleSchema({
contacts: {
type: Array,
optional: true
},
"contacts.$": {
type: Object
},
"contacts.$.comments": {
type: String,
label: "Comments From Salesmen"
}
});
I need to make it to the comments in the last block but I'm not having any luck.
When you access the first part contacts it returns object Object which is to be expected. But when I try to go deeper and reach the comments section I have no luck. I've tried contacts.comments - and contacts.comments[0] and nothing happens.
Here's a screenshot of my console showing the placement of the comment i need to reach
Console Array Comment Placement
Once I reach the comments I want to place them in the template I have below. Like I said I can get object Object to show in this form, but nothing else.
<template name="showPerson">
{{#with person}}
<h1>Show Person Details: {{name}}</h1>
<div class="row">
Comments: {{contacts.comments}}
</div>
{{/with}}
{{> update}}
</template>
New to javascript and meteor so please forgive my ignorance!!
You can also loop through contacts:
{{#each contacts}}
{{comments}} <!-- this might also need a loop -->
{{/each}}
If Contacts is a different collection, make sure you have a helper to return a cursor in order to loop
Related
If I have the following polymer element, how do I let the users of this element know about the structure of the object in dataSource. i.e If I have to declare and share Employee function, so that they can new Employee() and create an array. Whats the polymer way of sharing common data objects? Some seem to suggest behavior, but this isn't a behavior of the component, this is a data object with properties and no behavior.
<dom-module id="employee-list">
<template>
<ul>
<template is="dom-repeat" items="{{ dataSource }}">
<li>
<span>{{item.firstName}}</span>
</li>
</template>
</ul>
</template>
<script>
Polymer({
is: 'employee-list',
properties: {
dataSource: {
type: Array,
value: [{ firstName: "First 1", lastName: "Last 1" }]
}
}
});
</script>
</dom-module>
Use behaviors! Although the name is misleading, you can use behaviors to share properties.
A behavior is an object that looks similar to a typical Polymer
prototype. A behavior can define lifecycle callbacks, declared
properties, default attributes, observers, and listeners.
https://www.polymer-project.org/1.0/docs/devguide/behaviors.html
JS Bin example: http://jsbin.com/vuqumo/edit?html,output
Your users are going to use your element like this
<employee-list datasource="[[usersEmployeeList]]"></employee-list>
You need to tell them the format of the datasource in a jsdoc comment on the property. I don't know the format of the jsdoc comments properly, but look at the way the existing polymer elements do it.
I have this following function in my controller:
$scope.add = function(newItem){
if (!(newItem.title && newItem.text)) return;
var sanitized = {
title: newItem.title,
text: newItem.text,
date: Firebase.ServerValue.TIMESTAMP,
};
// $rootScope.currentUser is here bound with $firebaseObject(ref).$bindTo($rootScope, 'currentUser').
$rootScope.currentUser.list.push(sanitized);
// .list is an array: [].
};
And I utilise this in my view like follows:
<form name="newUp">
<input ng-model="newItem.title">
<textarea ng-model="newItem.text"></textarea>
<button ng-click="add(newItem)">Submit</button>
</form>
<div ng-repeat="item in currentUser.list | orderBy:'-date'">
<p>
<span>{{item.title}} <small> - {{item.date | date:'d MMM yy'}}</small></span><br>
<span ng-if="item.text"><small>{{item.text}}</small></span>
</p>
</div>
However after the submit button is clicked, and the item is saved to the firebase database, it displays on screen as:
{".sv":"timestamp"}
After I refresh the page entirely, it shows the item(s) with the correct timestamp(s). Is there a way to avoid this? Can I avoid using $firebaseArray to fix this?
I am using bower which has pulled down the following versions:
AngularFire 1.1.2
Firebase v2.2.7
AngularJS v1.4.1
From a quick glance there is a bug in work of $firebaseObject. It's obvious that it doesn't treat properly value of a special object Firebase.ServerValue.TIMESTAMP which tells server to put the timestamp on server-side. However this is not the case when adding same object in to $firebaseArray with a synchronized method $add.
Perhaps I am missing some kind of flush method for $firebaseObject but I can't find it.
In any case you should use $firebaseArray because your data is of type Array. And don't forget to use $add, $save and $remove as per docs
While running through the starter tutorial on EmberJS' site, a few things have me a little confused now.
One thing to note immediately is that I decided to use the ember 1.9.0beta4 with handlebars 2.0.0 instead of 1.8.1 / 1.3.0 included in the starter pack.
First the code included in the screencast:
app.js
App.Router.map(function() {
this.resource('about');
this.resource('posts');
this.resource('post', {path: ':post_id'})
});
App.PostsRoute = Ember.Route.extend({
model: function() {
return posts;
}
});
and
index.html
{{#each model}}
<tr><td>
{{#link-to 'post' this}}
{{title}} <small class='muted'>by {{author.name}}</small>
{{/link-to}}
</td></tr>
{{/each}}
This works exactly as expected and the requested post appears when clicked.
However, because I'm using 1.9.0, the preceding code produces a deprecated warning for {{#each}}, telling me to use {{#each foo in bar}} instead. I understand why this appears and agree the verbosity helps show exactly what data is being looped through.
So I change the line {{#each model}} to {{#each post in model}} and every bit of data disappears... I then try to change the code to:
updated index.html
{{#each post in model}}
<tr><td>
{{#link-to 'post' this}}
{{post.title}} <small class='muted'>by {{post.author.name}}</small>
{{/link-to}}
</td></tr>
{{/each}}
Great! The title and author's name once again appear for each post. But clicking either post gives me an undefined id. I change {{#link-to 'post' this}} to {{#link-to 'post' this.id}}. Same result. I change it to {{#link-to 'post' post.id}}. The id is now included but when I click the link I get this error:
Error while processing route: post Assertion Failed: You used the dynamic segment
post_id in your route post, but App.Post did not exist and you did not override
your route's `model` hook.
My questions are:
What happens internally that forces the post. prefix if I simply include the post in code? To me I should be able to use either this or continue to not need any prefix.
After adding post in to the each statement, what happens to this? Why does it no longer refer to the same object?
How can models be named to make it easier to categorize? post in model should really be post in posts but I haven't found a way to name the data container.
What is causing the error now that I'm no longer referring to the model as this? How can it be remedied?
Your frustration and questions are exactly the reason why the first syntax is deprecated and only the each post in ... form will be supported. Hopefully this answers your questions, and please respond if you need clarification.
In your first example where you use each model, the scope of the block changes to a post, meaning this refers to the current post in the loop. When you the form each post in ..., the scope does not change. When it does not change, that means this is actually referring to the previous scope (prior to the loop). In your example, the previous scope is the array controller, not the post object.
This is related to question 1. With the each post in ... format, this refers to whatever it was outside of the each block. It's not that something happens to this, it's that something does not happen to this because the scope doesn't change.
For better naming I usually setup a property as an alias to the content in the array controller:
posts: Ember.computed.alias('content')
In your original example, when you supply the link-to helper with this, you're passing the full post object. From what you've tried, it looks like this is the one thing you didn't do:
{#link-to 'post' post}}
I will try to answer your questions in order:
When you say {{#each model}} you are looping through the posts (array) in the model, so every time through the loop this is referring to the current post. Therefore when you say {{title}} you are really saying {{this.title}} When you are more explicit by saying {{#each post in model}} then each iteration through the loop is no longer referring to this and instead refers to the variable you made called post
Like mentioned in #1 above, this no longer refers to each individual iteration. I understand how you are thinking that perhaps still being able to use this (alongside post) would be convenient, but think about the following scenario. What happens when you have a nested {{#each}}? Would the implicit this refer to the outer array or inner array? If you really don't feel like typing the extra post. you can always use the {{#with post}} handlebars helper that scopes post back to this See the following example here
If you have a property in your model or controller, you can absolutely loop through that property as in {{#each color in colors}} See here for a working example
Finally, the link-to should be {{#link-to 'post' post}}
What I'm trying to accomplish is to return only one object to the model and loop through it's properties in a handlebars template. Thanx-a-Lot for any help!
My response looks like this:
{"U+554A":{
"id":1,
"unihex":"U+554A",
"num_reference":"呵",
"totalStrokes":10,
"kMandarin":"a\n",
"kDefinition":"exclamatory particle\n"},
"U+611B":{
"id":2,
"unihex":"U+611B",
"num_reference":"愛",
"totalStrokes":13,
"kMandarin":"\u00c3\u00a0i\n",
"kDefinition":"love, be fond of, like\n"}
}
I tried everything. The most obvious being these two, just as a tryout, but the ember inspector shows no model is set:
var sinograms = Ember.$.getJSON(apiurl);
return sinograms['U+554A'];
I also tried:
var sinograms = Ember.$.getJSON(apiurl);
return sinograms[0];
NB:
I can change the response format if necessary.
I know it works when I loose the object-keys (without "U+554A"), but then how do I select the matching character.
#abuani: Upon your request. Thanx btw.
//app.js
App = Ember.Application.create();
App.Router.map(function() {
this.resource('signup');
this.resource('login');
this.resource('profile');
this.resource('overview');
this.resource('practice');
});
App.OverviewRoute = Ember.Route.extend({
model: function() {
var url = 'http://localhost/~hiufung/RoadToChinese/index.php/api/sinograms/random?limit=2';
var sinograms = Ember.$.getJSON(url);
return sinograms;
}
});
//index.html (inline template)
<script type="text/x-handlebars" id="overview">
<header class="bar bar-nav">
<a class="icon icon-left pull-left" href="back"></a>
<h1 class="title">RoadToChinese</h1>
<a id="showRightPush" class="icon icon-gear pull-right" href="overview-settings"></a>
</header>
<div class="content">
<div class="content-padded">
{{#each object in model}}
<p>{{object.num_reference}}<p>
{{/each}}
</div>
</div>
</script>
I can't add a comment to your initial question, but can you please post a few other pieces of code:
The router that's loading this(I imagine this is being done in your model function), the setupController if you have one, and the template that's trying to render the object. Without this information, there's little I can do to help.
EDIT Since there's code:
I should have noticed, your model is return an objects when Ember expects the model to be an array of objects. The first thing you should do is make the return from the server an Array. If you don't have control over this, then you can change your model to return
return Ember.A([sinograms]);
And that should work.
After that though, you can remove the nested object within each object. If you don't remove that, then you also need to make the inner objects an Array so you can iterate over it.
Let me know how this goes.
Here's the JSBIN
http://emberjs.jsbin.com/aGUguJA/10
Using the bloggr example I built a list of posts and a post view and I've added 2 actions to the post template, Previous and Next.
App.PostController = Ember.ObjectController.extend({
actions:{
next: function(){
//Go to next object in a model
},
prev: function(){
//Go to previous object in a model
}}
});
I can't figure out how to make the Previous and Next to work. I have a strong feeling I need to be using an ArrayController but I still wouldn't know where to go from there.
One simple solution would be to add two fields/variables in your post object i.e.
{
id: '1',
title: "Object 1",
author: { name: "Awesome Person 1" },
date: new Date('01-01-2013'),
excerpt:"Lorem ..",
body:"Lore.."
next:2,
prev:null
}
So you either have this information available in your data or create App.Post objects that get instanciated from the data and you write a simple iteration to populate the fields within the model part of your App.PostsRoute.
Then you can modify your template accordingly and pass the object or id from the link-to of next and previous buttons.
look at a working example,
http://emberjs.jsbin.com/OxajiVi/1/
EDIT
The following example demostrates the solution using Ember class and objects to create the linked list, no previous and next fields in json data and also works when visiting a post directly,
http://emberjs.jsbin.com/uWAmUba/1
This could be helpful:
<button {{action "next"}}>Next</button>