meteor saying Iron Router is unresolved with Intellij - javascript

I'm using Intellij and Meteor to make an application and I'm trying to use Iron Router to create multiple pages, but when I call the Router in the Javascript file, it says that Router is an unresolved variable and that route is an unresolved function or method. I've checked the meteor folder and it appears that all the Iron Router files loaded fine. At the bottom of the root page I am working on it says
Oops, looks like there's no route on the client or the server for url:
"http://localhost:3000/."
If I navigate to http://localhost:3000/about, which is the only page I have a route set up for yet, the page is blank, except for my nav bar.
Here is my javascript file...
Items = new Mongo.Collection("items");
Found_items = new Mongo.Collection("found_items");
Router.route('home', {path: '/'}); // Add this route
Router.route('about', {path: '/about'});
if (Meteor.isClient) {
// This code only runs on the client
Template.body.helpers({
items: function () {
return Items.find({});
},
found_items: function () {
return Found_items.find({});
},
priceSum: function(){
var userItems = Found_items.find({
userId: this._id
}).fetch();
var prices = _.pluck(userItems, "price");
var totalTaxed = _.reduce(prices, function(sum, price){
var total = sum + parseFloat(price);
return total + (total * 0.04712);
}, 0);
return totalTaxed.toFixed(2);
},
calcTax: function () {
var userItems = Found_items.find({
userId: this._id
}).fetch();
var prices = _.pluck(userItems, "price");
var tax = _.reduce(prices, function(sum, price){
return (sum + parseFloat(price)) * 0.04712;
}, 0);
return tax.toFixed(2);
}
});
Template.body.events({
"submit .new-item": function (event) {
event.preventDefault();
var text = event.target.text.value;
Items.insert({
text: text,
createdAt: new Date(),
owner: Meteor.userId(),
username: Meteor.user().username
});
event.target.text.value = "";
}
});
Template.item.events({
"click .found": function (event, template) {
event.preventDefault();
var price = template.find('[name="price"]').value;
var text = template.find('.text').textContent;
Items.remove(this._id);
Found_items.insert({
text: text,
price: price
});
}
});
Template.body.events({
"click .remove": function(event) {
event.preventDefault();
Found_items.remove(this._id);
}
});
Accounts.ui.config({
passwordSignupFields: "USERNAME_ONLY"
});
}
And here is the HTML file
<head>
<title>Grocery List</title>
</head>
<template name="home">
<body>
<div>
<ul class="menu">
<li class="menuItem">{{> loginButtons}}</li>
<li class="menuItem">Home </li>
<li class="menuItem">About</li>
</ul>
</div>
{{#if currentUser}}
<div class="container">
<header>
<h1 id="title">Grocery List</h1>
<form class="new-item">
<input type="text" name="text" placeholder="Type to add new items" />
</form>
</header>
<ul>
{{#each items}}
{{> item}}
{{/each}}
</ul>
</div>
<div class="container">
<header>
<h1>Items Found</h1>
</header>
<ul>
{{#each found_items}}
{{> found}}
{{/each}}
</ul>
</div>
<div class="container">
<header>
<h3>
Tax: ${{calcTax}}
</h3>
<h2>
Total: ${{priceSum}}
</h2>
<button class="save">Save list</button>
</header>
</div>
{{else}}
<h3>Please log in first.</h3>
{{/if}}
</body>
</template>
<template name="item">
<li>
<button class="found">Got it!</button>
<input type="number" name="price" placeholder="Sale Price" />
<span class="text">{{text}}</span>
</li>
</template>
<template name="found">
<li>
<button class="remove">×</button>
<span class="text">{{text}}</span>
<span class="price">{{price}}</span>
</li>
</template>
<template name="about">
<head>
<title>About Grocery List</title>
</head>
<body>
<div>
<ul class="menu">
<li class="menuItem">{{> loginButtons}}</li>
<li class="menuItem">Home </li>
<li class="menuItem">About</li>
</ul>
</div>
<div class="container">
<header><h1>About</h1></header>
<p>This application was created using Meteor. It can be used to make, save and update grocery lists. Once the user is in the store, they can use it to check off items on the list, put in the price and see the total, with tax.<br>
Users can also save their previous lists to either reuse them, or compare current prices to previous ones.<br>
Future implementations of this page would also allow the user to change the tax rate depending on their location, and include coupons and other discounts in the pricing.</p>
</div>
</body>
</template>

Always add a route for the root.
Items = new Mongo.Collection("items");
Found_items = new Mongo.Collection("found_items");
Router.route('home', {path: '/'}); // Add this route
Router.route('about', {path: '/about'});
BTW, you have a head and body section within your template. That is rendered but does not have an effect in your browser.
Use the following syntax with IR's template helper pathFor:
<ul class="menu">
<li class="menuItem">{{> loginButtons}}</li>
<li class="menuItem">Home</li>
<li class="menuItem">About</li>
</ul>
In order to get your code working, I also fixed a couple of issues:
Removed head and body tags in templates.
Renamed Template.body.helpers to Template.home.helpers.
Renamed Template.body.events to Template.home.events.
Now it is adding new items to the collection and showing items.

you have to add a route with / to call localhost:3000
routing example
Router.configure({
layoutTemplate: 'layout',
});
Router.route('/', function () {
this.render('home');
},{
name: 'home'
});
Router.route('/about', function () {
this.render('about');
},{
name: 'about'
});
html
<template name="layout">
{{> yield}}
</template>
<template name="home">
<p>i am the homepage</p>
</template>
<template name="about">
<p>i am the about page</p>
</template>

Related

Angular JS expressions not evaluating

I've the following simple Angular JS trail, which contains the basic CRUD operations:
<html>
<head>
<title>CRUD</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
</head>
<body>
<div ng-app>
Simple Expression Evaluator:<br/>
<input ng-model="calculator"/><br/>
{{calculator + "=" + $eval(calculator)}}
</div>
<h3>CRUD - Comments</h3>
<div ng-app="commentapp">
<ul ng-controller="commentController">
<li ng-repeat="user in users">
{{user.name}} wrote "{{user.comment}}"
<br/>Delete
Edit
</li>
<li>
<input id="name" ng-model="current.name" value="{{current.name}}" />
<input id="name" ng-model="current.comment" value="{{current.comment}}" />
</li>
<li>
<button ng-click="save(current)">
Save
</button>
<button ng-click="addNew(current)">
Add New User
</button>
</li>
</ul>
</div>
<script>
var app = angular.module("commentapp", []);
app.controller("commentController", function($scope) {
$scope.users = [{
"name": "Qwe",
"comment": "Great!"
}];
$scope.current = {};
$scope.addNew = function(user) {
$scope.users.push(user);
};
$scope.edit = function(user) {
$scope.current = user;
};
$scope.save = function(user) {
$scope.current = {};
};
$scope.remove = function(user) {
var index = $scope.users.indexOf(user);
$scope.users.splice(index, 1);
};
});
</script>
</body>
</html>
However the output shows:
So, the expression evaluator works perfectly, which means Angular JS is tied up correctly. But the rest of the components don't work at all. Instead of Qwe, I get the expression {{user.name}}. What am I doing wrong here?
Hi I tried your script and seem working when I remove the first ng-app
nov the html part is like this
<h3>CRUD - Comments</h3>
<div ng-app="commentapp">
<ul ng-controller="commentController">
<li ng-repeat="user in users">
{{user.name}} wrote "{{user.comment}}"
<br/>Delete
Edit
</li>
<li>
<input id="name" ng-model="current.name" value="{{current.name}}" />
<input id="name" ng-model="current.comment" value="{{current.comment}}" />
</li>
<li>
<button ng-click="save(current)">
Save
</button>
<button ng-click="addNew(current)">
Add New User
</button>
</li>
</ul>
</div>
look at this fiddle
hope this help

Router.go( ) page render in Meteor

When I hit the /login route as triggered below, the correct route renders, but the top of the page begins with my template, not my layoutTemplate. I have to scroll up in order to see the layoutTemplate configured in the route.
if(! Meteor.userId()){
Session.set('single_post_not_logged_in', Session.get('post_id'));
Router.go('/login');
}
This is the route that gets triggerd:
Router.route('login', {
path: '/login',
layoutTemplate: 'loginLayoutTemplate',
template: 'login_template',
onBeforeAction: function(){
if(Meteor.loggingIn()){
var post_visited = Session.get('single_post_not_logged_in');
console.log(post_visited);
if(post_visited != undefined){
Router.go('/post/' + post_visited);
}
}
this.next();
}
});
And finally, here is the layout template that the route is leaving (layoutTemplate) and the new layout template (loginLayoutTemplate)
<body>
{{renderPage}}
</body>
<template name = 'layoutTemplate'>
{{> loginButtons}}
<a id = 'home_button' href="{{pathFor 'home'}}"><h1 id='layout_header'>snippetExchange</h1></a>
<div id='layout_header_row_2'>
<h2 id='layout_by_line'>valuable answers</h2>
<a id = 'new_post_button' href="{{pathFor 'new_post'}}">new post</a>
</div>
{{> yield}}
</template>
<template name = 'loginLayoutTemplate'>
<a id = 'home_button' href="{{pathFor 'home'}}"><h1 id='layout_header'>snippetExchange</h1></a>
<div id=''>
<h2 id='layout_by_line'>valuable answers</h2>
</div>
{{> yield}}
</template>
<template name = 'login_template'>
<h3>please login or create an account</h3>
{{> loginButtons}}
</template>
Try:
Template.login_template.onRendered(function(){
window.scrollTo(0, 0);
});

Meteor, How do I change a template (view) on event?

I'm building an app with two views: home & view list
When the user clicks on a list's name on the home view, it should change to the "view list" template. I've added a session variable called 'view', setting it to 'home' on startup. When a click event is detected on one of the items (list name) on the home screen, it changes the value of view to 'viewList'. Then in the HTML, I have an if statement to show the home template if 'view' is 'home', otherwise show the 'viewList' template.
I can tell the first part works because I'm outputting the value of 'view' and it does output the value "viewList" when you click on a list name, it just doesn't change the template.
What am I missing?
My code:
mylists.js:
Lists = new Mongo.Collection("lists");
if (Meteor.isClient) {
Meteor.startup( function() {
Session.set("view", "home");
});
Template.main.helpers({
view: function () {
return Session.get("view");
}
});
Template.home.helpers({
lists: function () {
return Lists.find({}, {sort: {lastUsed: -1}});
}
});
Template.home.events({
"submit #new-list": function (event) {
var name = event.target.listName.value;
Lists.insert ({
name: name,
createdAt: new Date(),
lastUsed: new Date()
});
},
"click .list-row": function (event) {
Session.set("view", "viewList");
}
});
}
mylists.html:
<head>
<title>My Lists</title>
</head>
<body>
{{> main}}
</body>
<template name="main">
{{view}}
{{#if view "home"}}
{{> home}}
{{else}}
{{> viewList}}
{{/if}}
</template>
<template name="home">
<header>
<h2>My Lists</h2>
</header>
<ul id="lists">
<li>
<form id="new-list">
<input type="text" name="listName" value="My List 1">
<input type="submit" value="Save">
</form>
</li>
{{#each lists}}
{{> list}}
{{/each}}
</ul>
</template>
<template name="viewList">
<header>
<h2>View List</h2>
</header>
<!-- list details will show here -->
</template>
<template name="list">
<li class="list-row" id="{{_id}}">{{name}}</li>
</template>
If you want to change from templates view i suggest you tu install the iron:router package.
run
meteor add iron:router
lester create the routes.js on the /lib folder
now lets do this step by step.
First create 1 template on myAppName/client/views/layout.html
<template name="layout">
{{> yield}}
</template>
and update the routes.js with this code.
Router.configure({
layoutTemplate: 'layout' // here we say that layout template will be our main layout
});
Now on the same routes.js create this 2 routes.
Router.route('/home', function () {
this.render('home');
});
Router.route('/viewList', function () {
this.render('viewList');
});
With this if you navigate to localhost:3000/home or /viewList you will see the html content on there.
NOTES: <header> inside the templates you don't need it.
Now this is just an example because i don't really know whats your main idea here.
you are calling {{#each lists}} inside the home template, so whats the point of having the viewList template?
Now if you want to create individual and dynamic routes for each list you can try this.
Router.map(function () {
this.route('listViews', {
path: '/listViews/:_id',
waitOn: function(){
return Meteor.subscribe('lists')
},
data: function(){
return Lists.findOne({_id: this.params._id});
}
});
});
Now with this, you have dynamic templates for each object on the List collection, if you go to localhost:300/listView/35dwq358ew for example you will get render the listView with some data.
you can do stuff like this inside the template list
<template name="list">
<li class="list-row" id="{{_id}}">{{name}}</li>
<li>Check this List in detail</li>
</template>
and the viewList template will look like this.
<template name="viewList">
<h2>{{title}}</h2>
<!-- list details will show here -->
{{informationAboutList}}
</template>

Iron-router, Router.go() doesn't full render a template

I have a login system with the following layout :
<template name="loginLayout">
<div class="container">
<div class="flat-form">
<ul class="tabs">
<li> <a id="login" class="{{#if isRouteActive 'login' }}active{{/if}}" href="{{ pathFor 'login' }}">Login</a> </li>
<li> <a id="registration" class="{{#if isRouteActive 'registration' }}active{{/if}}" href="{{ pathFor 'registration' }}">Register</a> </li>
<li> <a id="resetPassword" class="{{#if isRouteActive 'resetPassword' }}active{{/if}}" href="{{ pathFor 'resetPassword' }}">Reset Password</a> </li>
</ul>
{{> yield }}
</div>
</div> </template>
According to which link a user hits, meteor renders the correct template in the yield field.
This works fine, but when a user logs in, the private page is rendered within this layout which is wrong. I don't understand why this is happening, if I specify the layout only for the login routes.
Routes file :
Router.map( function () {
this.route( 'login',
{
path : '/login',
layoutTemplate: 'loginLayout',
yieldTemplate : 'login',
data : {
appName : "test",
welcomeMessage : "test."
}
}
);
this.route( 'registration',
{
path : '/registration',
layoutTemplate: 'loginLayout',
yieldTemplate:'registration',
data : {}
}
);
this.route( 'resetPassword',
{
path : '/resetPassword',
layoutTemplate: 'loginLayout',
yieldTemplate : 'resetPassword',
data : {}
}
);
this.route('library');
});
var mustBeSignedIn = function(pause) {
if (!(Meteor.user() || Meteor.loggingIn())) {
Router.go('login');
pause();
}
};
Router.onBeforeAction(mustBeSignedIn, {except: ['login', 'registration', 'resetPassword']});
Login.js
Template.login.events({
'submit #login-form' : function(e, t){
e.preventDefault();
// retrieve the input field values
var userName = t.find('#login-email').value
, password = t.find('#login-password').value;
Meteor.loginWithPassword(userName, password, function(err){
if (err) {
console.log("Error when loggin ");
console.log(err.reason);
} else {
console.log("user logged in");
/***** REDIRECT ******/
Router.go('library');
}
});
return false;
}
});
logi.js template :
<template name="login">
<div id="login" class="form-action">
<h1>Login on {{ appName }} </h1>
<p> {{ welcomeMessage }} </p>
<form id="login-form">
<ul>
<li> <input id="login-email" type="text" placeholder="Username" /></li>
<li> <input id="login-password" type="password" placeholder="Password" /></li>
<li> <input id="submit" type="submit" value="Login" class="button" /></li>
</ul>
</form>
</div>
</template>
I have also noticed that when I use the method "go" to redirect a user to a given route, the data field is reset. Whereas, when I write down the url every thing works fine.
Full source
The way it worked for me was to create an additional controller for my major layout and render my header and footer template again with and layoutTemplate, yieldTemplate and action: function(){}.
Here an example route:
Router.route('einstellungen', function() { // settings
this.render('Settings', {
to: 'interfaceContainer'
});
}, {
controller: 'InterfaceController'
});
And only after adding the following code, Router.go('/einstellungen'); works in a way that the entire layout plus yield layouts are rendered.
InterfaceController = RouteController.extend({
layoutTemplate: 'interfaceLayout',
yieldTemplates: {
'Header': {
to: 'interfaceHeader'
},
'Footer': {
to: 'interfaceFooter'
}
},
action: function() {
this.render('Header', {
to: 'interfaceHeader'
});
this.render('Footer', {
to: 'interfaceFooter'
});
}
});
I also added:
Router.configure({
layoutTemplate: 'interfaceLayout',
yieldTemplates: {
'Header': {
to: 'interfaceHeader'
},
'Footer': {
to: 'interfaceFooter'
}
}
});
But this does not seem to have any impact on Router.go();
See also:
https://forums.meteor.com/t/custom-layout-for-a-specific-route-not-displaying-with-iron-router/5758
https://github.com/iron-meteor/iron-router/blob/devel/Guide.md#creating-route-controllers

PagerJS how to build a navbar?

My goal is to write some reusable code to render basic navbars, since it would be a very repetitive task. The following features are my first goal:
Each page should be rendered in a foreach binding
Each page should grab the active state reading current route
Each page should be loaded either async or inline
Here's my first attempt. I want markup to be something like this
<ul data-bind='foreach: pages'>
<li>
<!--
[1]
Here a toggler is needed for active/no-active status,
i.e. a class binding.
-->
<a data-bind='html: caption, click: $data.load'></a>
</li>
</ul>
Each page item should look something like this
function PageItem(id, caption) {
this.id= id;
this.caption = caption;
this.page = pager.page.find(id);
this.load = function() {
// [2]
// Code here to trigger page load,
// i.e. this.page.async(someCallback, this.id);
}
this.active = function() {
// [3]
return this.page.isVisible();
}
}
Usage goal:
function VM() {
var self = this;
self.pages = [];
self.pages.push(new PageItem('dashboard', "<i class='fa-icon-home'></i>"));
self.pages.push(new PageItem('offerJoin', 'Offer'));
}
var vm = new VM();
pager.extendWithPage(vm)
ko.applyBindings(vm);
pager.start('dashboard');
I need help with [1], [2] and [3] topics. Any pointer?
Here is how you can built it. This is only example.
The structure of app is like this which you can customize.
app/
/index.js
/index.html/
/lib/
/pager.js
/require.js
/knockout-3.0.0beta.js
/views/
/test.html
/test1.html
And here is how you can do it.
First index.html
<html>
<head>
<script data-main="index.js" type="text/javascript" src="lib/require.js"></script>
</head>
<body>
<div class="container" style="padding-top: 30px;">
<span id="span" onclick = 'clickme(this)'>I am span</span>
<div data-bind="page: {id: 'start' , title : 'First Page'}">
you are currently viewing the content of first page. <br />
first child<br />
second child<br />
<br />
<div data-bind="page: {id: 'deep', title : 'Second Page',role: 'start', source: 'views/test1.html'}">
you are currently viewing the content of first page inside First Page.
<br />
<a data-bind="page-href :'../second'" >Second Child</a>
</div>
<div data-bind="page: {id: 'second', title : 'Second Page', source: 'views/test.html'}">
you are currently viewing the content of second page inside Second Page.
<br />
<a data-bind="page-href :'../deep'" >First Child</a>
</div>
<br />
<br />
<br />
Go to Structure
</div>
<div data-bind="page: {id: 'structure', title : 'Second Page'}">
you are currently viewing the content of second page.<br />
Go to Start
</div>
</div>
</body>
</html>
Next index.js
requirejs.config({
shim:{
bootstrap:['jquery'],
hashchange:['jquery']
},
paths:{
jquery:'lib/jquery-1.10.2',
knockout:'lib/knockout-3.0.0beta',
pager:'lib/pager'
}
});
requirejs(['jquery','knockout','pager'], function ($, ko,pager) {
function PagerViewModel(){
var self = this;
}
$(function () {
pager.Href.hash = '#!/';
pager.extendWithPage(PagerViewModel.prototype);
ko.applyBindings(new PagerViewModel());
pager.start();
});
});
And the views to load
test.html
<h3>Second Page</h3>
<p>This is a test view loaded by pager.js</p>
<p>The view loads with ajax request when the main page loads</p>
<p>All the pages that need to be loaded are loaded only once with ajax</p>
<p>while navigating the pages are not loaded again</p>
<a data-bind="page-href :'../deep'" href="#">First Child</a>
test1.html
<h3>First Page</h3>
<p>This is yet another page loaded by pager.js</p>
<a data-bind="page-href :'../second'" href="#">Second Child</a>
You can see how i created navigation bar the titles are first child and second child.
You can download the demo here

Categories

Resources