Exception in defer callback: Error: No such template: autoform - javascript

Assuming I did everything like aldeed described here to create a custom form template. What did I forget or where is the mistake that the autoform tag is not present?
Actual html examle:
<template name="afType_talkBar">
{{#autoform schema=Schema.Nachrichten id="sendMessageForm" type="insert"}}
<fieldset class="clubChat__input">
<div class="clubChat__message-bar">
{{> afQuickField name='chatroomId'}}
{{> afQuickField name='userName'}}
<div class="form-group{{#if afFieldIsInvalid name='content'}} has-error{{/if}}">
<div class="input-group">
<span class="input-group-addon">$</span>
{{> afFieldInput name='content'}}
<span class="input-group-addon">/each</span>
</div>
{{#if afFieldIsInvalid name='content'}}
<span class="help-block">{{afFieldMessage name='content'}}</span>
{{/if}}
</div>
<input type="submit" value="{{_ 'chatAction.send'}}">
</div>
</fieldset>
{{/autoform}}
</template>
And the client side talkBar.js
import './talkBar.html';
// Import necessary js Packages
import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { Nachrichten } from '../../../api/nachrichten/nachrichten';
Bonus question. Inserting
Template.talkBar.helpers({
nachrichtenCollection(){
return Nachrichten;
}
});
results into an Uncaught TypeError: Cannot read property 'helpers' of undefined
Looks like i'm missing something fundamental

Your template name in helper definition is incorrect. The pattern is as below
Template.Template_Name.helpers({});
You have named incorrect template name. It must be as below,
Template.afType_talkBar.helpers({});
Also you used relative path while you are declaring a Collection in client JS file. You can use as below,
import { nachrichten } from '/import/api/nachrichten/nachrichten.js';
This is much better convention because you may cut paste your js file anywhere else as per need and you may also create many js files and shuffle them in future, so the path will change as per your declaration.

Typo Error instead of autoform it must be autoForm
Correct code should look like this:
<template name="afType_talkBar">
{{#autoForm schema=Schema.Nachrichten id="sendMessageForm" type="insert"}}
<fieldset class="clubChat__input">
<div class="clubChat__message-bar">
{{> afQuickField name='chatroomId'}}
{{> afQuickField name='userName'}}
<div class="form-group{{#if afFieldIsInvalid name='content'}} has-error{{/if}}">
<div class="input-group">
<span class="input-group-addon">$</span>
{{> afFieldInput name='content'}}
<span class="input-group-addon">/each</span>
</div>
{{#if afFieldIsInvalid name='content'}}
<span class="help-block">{{afFieldMessage name='content'}}</span>
{{/if}}
</div>
<input type="submit" value="{{_ 'chatAction.send'}}">
</div>
</fieldset>
{{/autoForm}}
</template>

Related

How to add an input-group-addon ( Bootstrap CSS ) onto an Alpaca.js field

Hoping for some assistance , I require an appended and prepended Input group addon As shown here on bootstrap.com into a alpaca.js form.
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet"/>
<div class="input-group"><span class="input-group-addon">$</span>
<input type="text" class="form-control" placeholder="Recipient's username" aria-describedby="basic-addon2">
<span class="input-group-addon" id="basic-addon2">#example.com</span>
</div>
The template (handlebars) should look like the snippet below, however documentation on the site does not cover custom options and template editing like this.
<script type="text/x-handlebars-template">
{{#if options.component}}
<div class="input-group">
{{#if options.prepend}}
<span class="input-group-addon" id="basic-addon-prepend">{{options.prepend}}</span>
{{/if}}
{{/if}}
<input type="{{inputType}}" id="{{id}}" {{#if options.placeholder}}placeholder="{{options.placeholder}}"{{/if}} {{#if options.size}}size="{{options.size}}"{{/if}} {{#if options.readonly}}readonly="readonly"{{/if}} {{#if name}}name="{{name}}"{{/if}} {{#each options.data}}data-{{#key}}="{{this}}"{{/each}} {{#each options.attributes}}{{#key}}="{{this}}"{{/each}}/>
{{#if options.component}}
{{#if options.append}}
<span class="input-group-addon" id="basic-addon-append">{{options.append}}</span>
{{/if}}
</div>
{{/if}}
</script>
The question would be : Where should this code be changed ,and how should the modified template be executed ?
Thanks in advance!
If you're tring to use a custom template for a field you should set it into view object like this :
"view": {
"fields": {
"/username": {
"templates": {
"control-text": "#input-group-addon-template"
}
}
}
}
Here's a working fiddle for this. If this isn't what you're looking for please fill me with more details and I'll be glad to help :)

Checking equality in Blaze?

The user can only delete a post if he was the one who posted it.However a user can see all the posts.The javascript code is:
var postedBy = Meteor.user();
var currentPost = this._id;
Posts.insert({
name:postName,
createdAt:new Date(),
postId:currentPost,
postedBy:postedBy
});
The HTML code is:
<template name="posts">
{{#if currentUser}}
{{> addPost}}
<ul>
{{#each post}}
<li>{{> postItem}}</li>
{{/each}}
</ul>
{{/if}}
</template>
<template name="postItem">
<li>
<h4>{{name}}</h4>
<i>Posted by {{postedBy.username}} on {{createdAt}}</i>
[Delete]
</li>
</template>
<template name='addPost'>
<input type='text' placeholder='Add post here' name='postName' id ='myinput'>
<button class="btn btn" type="button" id='btn'>Post</button>
</template>
Both currentUser.username and postedBy.username are displaying the names of the logged in user and the user who posted a particular post respectively.
I am trying to work with the Delete anchor tag.
{{#if currentUser.username==postedBy.username}}
[Delete]
{{/if}}
But it shows error in command prompt.I know it is wrong but I can't think of any other way.How do i write this 'if' statement to check if the current user was the one who posted this post?
Please help as I am new to Meteor.Sorry for bad English.
You can't use arbitrary JavaScript expressions in spacebars. Add a helper like this:
Template.postItem.helpers({
canDelete: function (){
return Meteor.user().username === this.postedBy.username;
}
});
Which you can then use in your template like this:
{{#if canDelete}}
Delete
{{/if}}
Also note, instead of copying the user object into each post, the recommended way is to store the user's id in postedBy.

Setting the data context for a template defined by a package

Here's the relevant code template code:
<!-- display a list of users -->
<template name="available_user_list">
<h2 class="cha_heading">Choose someone to chat with:</h2>
<div class="row">
{{#each users}}
{{> available_user}}
{{/each}}
</div>
</template>
<!-- display an individual user -->
<template name="available_user">
<div class="col-md-2">
<div class="user_avatar">
{{#if isMyUser _id}}
<div class="bg-success">
{{> avatar user=this shape="circle"}}
<div class="user_name">{{getUsername _id}} (YOU)</div>
</div>
{{else}}
<a href="/chat/{{_id}}">
{{> avatar user=this shape="circle"}}
<div class="user_name">{{getUsername _id}}</div>
</a>
{{/if}}
</div>
</div>
</template>
<template name="chat_page">
<h2>Type in the box below to send a message!</h2>
<div class="row">
<div class="col-md-12">
<div class="well well-lg">
{{#each messages}}
{{> chat_message}}
{{/each}}
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<form class="js-send-chat">
<input class="input" type="text" name="chat" placeholder="type a message here...">
<button class="btn btn-default">send</button>
</form>
</div>
</div>
</template>
<!-- simple template that displays a message -->
<template name="chat_message">
<div class="chat-message">
{{> avatar user=user size="small" shape="circle"}} <div class="chat-center">{{user}}: {{text}}</div>
</div>
</template>
and the template helpers:
Template.available_user_list.helpers({
users:function(){
return Meteor.users.find();
}
})
Template.available_user.helpers({
getUsername:function(userId){
user = Meteor.users.findOne({_id:userId});
return user.username;
},
isMyUser:function(userId){
if (userId == Meteor.userId()){
return true;
}
else {
return false;
}
}
})
Template.chat_page.helpers({
messages:function(){
var chat = Chats.findOne({_id:Session.get("chatId")});
return chat.messages;
},
other_user:function(){
return ""
},
})
Template.chat_message.helpers({
user: Meteor.user()
})
I'm making an website where users can log in and chat with each other. I've downloaded the utilities:avatar package to show the avatars of the users. The avatar image is based on the first initial of the username of the user. When I render the avatar template in the template available_user with the code {{> avatar user=this shape="circle"}}, it shows the initials in the avatars fine because it's with the context of the users collection.
I also want to show the avatar when a user sends a message but the template chat_message is within the data context of an array inside the chats collection. So it only shows the default avatar without the initial.
the documentation for the package doesn't quite specify how I can set the template parameter for user or userId. Can someone please help with this issue?
I figured it out. I included the user id into each object in the messages array under the field userId and in the template I set it as {{> avatar userId=userId size="small" shape="circle"}}

How to get model data on view in Ember JS

How can i access model data in my view template in Ember JS ?
Is it saved in a global variable?
Here's my template:
<script type="text/x-handlebars" data-template-name="todo-list">
{{#if length}}
<section id="main">
{{#if canToggle}}
{{input type="checkbox" id="toggle-all" checked=allTodos.allAreDone}}
{{/if}}
<ul id="todo-list">
{{#each}}
<li {{bind-attr class="isCompleted:completed isEditing:editing"}}>
{{#if isEditing}}
{{todo-input type="text" class="edit" value=bufferedTitle focus-out="doneEditing" insert-newline="doneEditing" escape-press="cancelEditing"}}
{{else}}
{{input type="checkbox" class="toggle" checked=isCompleted}}
<label {{action "editTodo" on="doubleClick"}}>{{title}}</label>
<button {{action "removeTodo"}} class="destroy"></button>
{{/if}}
</li>
{{/each}}
</ul>
</section>
{{/if}}
</script>
<script type="text/x-handlebars" data-template-name="todos">
<section id="todoapp">
<header id="header">
<h1>todos</h1>
{{todo-input id="new-todo" type="text" value=newTitle action="createTodo" placeholder="What needs to be done?"}}
</header>
{{outlet}}
{{#if length}}
<footer id="footer">
<span id="todo-count"><strong>{{remaining.length}}</strong> {{pluralize 'item' remaining.length}} left</span>
<ul id="filters">
<li>
{{#link-to "todos.index" activeClass="selected"}}All{{/link-to}}
</li>
<li>
{{#link-to "todos.active" activeClass="selected"}}Active{{/link-to}}
</li>
<li>
{{#link-to "todos.completed" activeClass="selected"}}Completed{{/link-to}}
</li>
</ul>
{{#if completed.length}}
<button id="clear-completed" {{action "clearCompleted"}}>Clear completed</button>
{{/if}}
</footer>
{{/if}}
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
</footer>
</script>
Thank you!
The Route sets up a "model" variable that is accessible by your template via:
{{model.myProperty}} or
{{myProperty}} (Before Ember2 this way would look up into your Controller Computed Properties. If none exists, then it would proxy through model.myProperty. See this deprecation)
In order to make the model data accessible "outisde of Ember" your can:
Create a Component
From the template, call it and pass the data down to it
Use onDidInsertElement and read the property. From now on, you can make it accessible to "the outisde world"
OBS: I'm not sure that's a good practice though.
JS BIN: http://emberjs.jsbin.com/dapidu/3/edit?html,js,output
If you want to use it in a different template (which is linked to a different controller I guess?), you can create an alias in the other controller like this :
//Include the first controller
needs: ['todoController'],
length: Ember.computed.alias('controllers.todoController.length'),
I don't have much precisions on how you built your application, but if you can't access it from the other template, it means your changing the application context (firstController -> secondController).
Do you have 2 controllers?

Meteor.js affecting only newly inserted child template

These are templates:
<template name="postsList">
{{#each posts}}
{{>postItem}}
{{/each}}
</template>
<template name="postItem">
<div class="more-less">
<div class="more-block">
<p>{{{text}}}</p>
</div>
<p class="continued">…</p>
[ + ]
</div>
</template>
When posts is updated with new post, postItem is inserted to postsLists. How can I apply this only for new inserted postItem template:
$('.more-less .more-block').css('height', 20).css('overflow', 'hidden');
Template.postItem.rendered affects all posts in page, but I need to affect only newly inserted post without affecting existing ones.
I'm going to assume new posts are added to the top of the list? if so...
<template name="postsList">
<div class="posts-list">
{{#each posts}}
{{>postItem}}
{{/each}}
</div>
</template>
<template name="postItem">
<div class="more-less">
<div class="more-block">
<p>{{{text}}}</p>
</div>
<p class="continued">…</p>
[ + ]
</div>
</template>
You can simply achieve this with CSS:
.posts-list .more-less:first-child .more-block {
height: 20px;
overflow: hidden;
}
No need to use JavaScript and worry about reactivity and DOM mutation.

Categories

Resources