Meteor: Adding sortable with rubaxa:sortable package - javascript

I try to integrate rubaxa:sortable to make my list sortable.
client/helpers.js
Template.getElements.helpers({
children: function() {
return Articles.find({ parent: this._id }, {sort: {order: 1}});
}
});
server/publications.js
Meteor.publish('articles', function() { return Articles.find({}, {sort: {slug: 1}}); });
Sortable.collections = 'articles';
template
<template name="getElements">
<ul class="sortable">
{{#each children}}
{{#sortable items=Articles sortField="order"}}
<li data-id="{{_id}}"><input type="text" name="keyword" value="{{title}}"></li>
{{/sortable}}
{{/each}}
</ul>
</template>
In the documentation (https://atmospherejs.com/rubaxa/sortable) I see the info:
Client:
{{#sortable items=<collection|cursor|array> sortField="order"}}
Server:
Sortable.collections = <collectionName>; // the name, not the variable
So what am I doing wrong? Right now no list-element is beeing shown.

I'm not an expert but based on integration this will fix your issues.
Server JS
Update the declaration to include the collation name in [].
Sortable.collections = ['articles'];
HTML Template
remove the following:
{{#each children}}
{{/each}}
Regards,
Vince

Related

Collecting text submitted in input field with ember-rails

I am following an ember-rails tutorial. It's using coffeescript and I'm writing in javascript. Essentially I have a form that when I submit text on it it should place the text below.
My controller looks like this:
Emberapp.ApplicationController = Ember.Controller.extend({
entries: [],
actions: {
addEntry: function(){
this.entries.pushObject name: this.get('newEntryName');
this.set('newEntryName', "");
}
}
});
My template looks like this
<div id = "container">
<h1>Emberails</h1>
{{ input value=newEntryName enter='addEntry' }}
<ul>
{{#each entries}}
<li>{{name}}</li>
{{/each}}
</ul>
</div>
When I reload the page I get an error stating that 'name: this.get('newEntryName');' is an Unexpected identifier. I've been checking for the syntax rules online but I'm not sure if it is a coffeescript to javascript error or something else.
this.entries.pushObject name: this.get('newEntryName');`
is not valid JS. You want do do
this.entries.pushObject({name: this.get('newEntryName')});
Controller,
Emberapp.ApplicationController = Ember.Controller.extend({
newEntryName: '',
entries: [],
actions: {
addEntry: function(){
this.get('entries').pushObject({name: this.get('newEntryName')});
this.set('newEntryName', "");
}
}
});
in hbs,
<div id = "container">
<h1>Emberails</h1>
{{ input value=newEntryName enter='addEntry' }}
<ul>
{{#each entries as |value|}}
<li>{{value.name}}</li>
{{/each}}
</ul>
</div>
Like Lux suggested consider ember-cli and read http://guides.emberjs.com

Meteor Templates helpers and access to collections' fields [duplicate]

This question already has answers here:
How do I check if an array includes a value in JavaScript?
(60 answers)
Closed 7 years ago.
I have two collections:
Group = {
users: [Array_of_User]
}
User = {
name: _string_
}
I'm listing groups ans I'm trying to know in the template if a user is in the groups:
mytemplate.js
Template.mytemplate.helpers({
groups: function(){
return Groups.find();
},
currentUsername: 'test'
});
mytemplate.html
<template name="main">
<ul>
{{#each groups}}
<li>
{{#if [the group contains currentUsername] }}
contains
{{else}}
doesn't contain
{{/if}}
</li>
{{/each}}
</ul>
</template>
The question is: what can I put on the helpers and instead of [the group contains currentUsername] to make it work?
Also, I'm not saying this is the way to do it. I'm open to any suggestions even if it means I have to change a lot.
You could use the Underscore.js function _.findWhere(list, properties) to check whether the group contains the username:
if (Meteor.isClient) {
Template.main.helpers({
groups: function() {
return Groups.find();
},
currentUsername: 'Matthias',
isInGroup: function(username) {
return !!_.findWhere(this.users, {
name: username
});
}
});
}
<template name="main">
<ul>
{{#each groups}}
<li>
{{#if isInGroup currentUsername}}
contains
{{else}}
doesn't contain
{{/if}}
</li>
{{/each}}
</ul>
</template>
if (Meteor.isServer) {
Meteor.startup(function() {
Groups.insert({
users: [{
name: "Matthias"
}, {
name: "Angie"
}]
});
});
}
Here is a MeteorPad.
Within your each block, your data context becomes the current group that is being iterated over. Therefore you can write a helper method that references that current data context like this:
userInGroup: function(username) {
var userInGroup;
this.forEach(function(groupUsername) {
if (username == groupUsername) {
userInGroup = true;
}
};
return userInGroup;
}
'this' within the userInGroup template helper references the current group as long as you use the helper within an a group iteration.
You can then use the helper like this:
<template name="main">
<ul>
{{#each groups}}
<li>
{{#if userInGroup currentUsername}}
contains
{{else}}
doesn't contain
{{/if}}
</li>
{{/each}}
</ul>
</template>

How do I use a subscription in flow-router?

// server/publications.js
Meteor.publish('crewMessages', function(crewId) {
return CrewMessages.find({crewId: crewId}, {sort: {submitted: -1}, limit: 100});
});
// lib/router.js
FlowRouter.route('/crew/:crewSlug', {
subscriptions: function(params) {
console.log("Subscribed to this crew's chat messages:", params.crewSlug);
this.register('crewMessages', Meteor.subscribe('crewMessages', params.crewSlug));
},
action: function(params) {
FlowLayout.render("layout", { content: 'crew' });
}
});
And inside my crew.html template:
<div class="container">
{{> crewChat}}
</div>
And my crewChat.html/js:
Template.crewChat.helpers({
messages: function() {
return CrewMessages.find({}, {sort: {submitted: -1}});
}
});
<div class="ui feed">
{{#each messages}}
{{> crewChatMessage}}
{{/each}}
</div>
In my crewChat.js file, how can I use the subscription I set in Flow-router?
I create a functional example for you at MeteorPad
http://meteorpad.com/pad/Ba5DTe94NjFi3ZTPA/Playground_Flow-Router_Chat
Most important to your question is, that you just can use the Collection inside your template with Collection.find() because you are only subscribed to the crews messages via route subscription.
Each message can be accessed as normal document see template showChatMessage
Hope that makes it clear for you
Cheers
Tom
PS: You can also change the url inside the meteorpad to also switch to chats for team2 and team3

Using Iron Router to set a query variable

I am trying to use Iron Router to call a page and filter results by the route. Effectively, the application allows you to create items. Items include an array that can have 0 to many tags:
Item: {
_id: <assigned by application>,
itemTags: []
}
The dropdown list on the navbar collects all tags from the items, does some cleaning, and then drops them into the dropdown menu:
// HTML
<template name="header">
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<ul class="nav navbar-nav">
<li class="dropdown">
Select List to View <span class="caret"></span>
<ul class="dropdown-menu" role="menu">
<li>All List Items</li>
<li class="divider"></li>
{{#each uniqueTags}}
<li>{{this}}</li>
{{/each}}
</ul>
</li>
</ul>
</div>
</div>
</nav>
</template>
// JS
Template.header.helpers({
uniqueTags: function() {
var allItems = Items.find({checked: false});
var uniqueTags = allItems.map((function(allItems) {return allItems.itemTags;}));
uniqueTags = _.flatten(uniqueTags);
uniqueTags = _.compact(uniqueTags);
uniqueTags = _.uniq(uniqueTags);
uniqueTags = _.sortBy(uniqueTags, function (name) {return name;});
return uniqueTags;
}
});
The router then sends you to "/list/". Everything up to this point works great. But then it falls apart. My problem is twofold:
1) How do I appropriately grab the data context of just the items that have the tag listed somewhere in the array?
2) How do I display those items on the "list" page? I have zero idea what should be in list.js to handle the returned data context
My current code is below, but it's hacked up and clearly not working :)
// JS - router.js
Router.route('/list/:tagName', {
name: 'list',
data: function() {
return Items.find({$and: [
{checked: false}, {listItem: true}, {itemTags: {$in: ['this.params.tagName']}}
]});
}
});
// HTML - list.html
<template name="list">
<h3><span class="label label-default view-list">List</span></h3>
{{#each listItems}}
{{> item}}
{{/each}}
</template>
// JS - list.js
Template.list.helpers({
listItems: function() {
<somehow use the returned data context>
}
});
Thanks for your help!
This would work
Router.route('/list/:tagName', {
name: 'list',
data: function() {
return { 'listItems' : Items.find({$and: [
{checked: false}, {listItem: true}, {itemTags: {$in: [this.params.tagName]}}
]}) };
}
});
// HTML - list.html
<template name="list">
<h3><span class="label label-default view-list">List</span></h3>
{{#each listItems}}
{{> item}}
{{/each}}
</template>
// You have to write a item template
// JS - list.js
Template.list.helpers({
//listItems: function() {
// this helper is not required
// you could access the data by this.data.listItems
//<somehow use the returned data context>
//}
});

Handlebars.js using ../ to reference parent Context

Lets say I have the following JSON and handlebars.js template :
JSON
{
rootPath: '/some/path/',
items:[ {
title: 'Hello World',
href: 'hello-world'
}, {
title: 'About',
href: 'about'
}, {
title: 'Latest News',
href: 'latest-news'
}
}
Template
<script id="test-template" type="text/x-handlebars-template">
<ul class="nav">
{{#each items}}
<li>{{title}}</li>
{{/each}}
</ul>
</script>
The template above works, until I want to filter items - lets say to have 2 lists one odd and the other even, here's a simple template for odd :
<script id="test-template" type="text/x-handlebars-template">
<ul class="nav">
{{#each items}}
{{#isOdd #index}}
<li>{{title}}</li>
{{/isOdd}}
{{/each}}
</ul>
</script>
And the registered helper :
// isOdd, helper to identify Odd items
Handlebars.registerHelper('isOdd', function (rawValue, options) {
if (+rawValue % 2) {
return options.fn(this);
} else {
return options.inverse(this);
}
});
The helpers work as expected and only the Odd items are rendered, however the reference to the parent context becomes lost, so the {{../rootPath}} directive ~~fails to render~~ renders an empty value.
Is there a way to pass the Parent context through the block Helper?
Change this:
<a href="{{../rootPath}}{{href}}">
to this:
<a href="{{../../rootPath}}{{href}}">
Why? because the if statement is in an inner context so first you need to go up a level and that's why you have to add ../
See more details in:
https://github.com/wycats/handlebars.js/issues/196

Categories

Resources