FlowRouter is not defined in individual templates - javascript

Using Meteor, I started with a default Meteor project with...
meteor create --full
I added a route, in router.js, like so:
FlowRouter.route('/group/:_id', {
name: 'App.groups.show',
action() {
if (!logged_in()) {
FlowRouter.go("App.home");
}
else {
this.render('App_body', 'Group');
}
},
});
router.js is here:
/imports/startup/client/router.js
The Group template is this:
<template name="Group">
{{> user_group}}
</template>
And for user_group, I have this:
Template.user_group.onCreated(function user_groupOnCreated() {
console.log("id", FlowRouter.getParam('_id'));
});
This results in:
ReferenceError: FlowRouter is not defined
at Blaze.TemplateInstance.user_groupOnCreated (user-group.js:46)
at template.js:119
at Function.Template._withTemplateInstanceFunc (template.js:490)
at fireCallbacks (template.js:115)
at Blaze.View.<anonymous> (template.js:195)
at fireCallbacks (view.js:276)
at Object.Tracker.nonreactive (tracker.js:603)
at view.js:273
at Object.Blaze._withCurrentView (view.js:533)
at Object.Blaze._fireCallbacks (view.js:272)
I also do not have access to FlowRouter.go in my templates.
What am I missing?

You need to import FlowRouter in every js that actively uses it (in your example the Template):
import { FlowRouter } from 'meteor/kadira:flow-router'
Template.user_group.onCreated(function user_groupOnCreated() {
console.log("id", FlowRouter.getParam('_id'))
})

Related

Ember - Cannot create helper in test

I'm trying to create a helper for my test in order to simulate a model.
I'm receiving the follow error, though:
: makeInventoryObjects is not defined
My test helper:
// ../tests/helpers/make-inventory-objects.js
import Ember from 'ember';
export default Ember.Test.registerAsyncHelper('makeInventoryObjects', function() {
const inventoryObjects = [{'id': 1, 'name': 'test'}];
return inventoryObjects;
});
My start-app in helpers contains application.injectTestHelpers();
The test which is failing:
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
// I tried to import manually too and it did not work
// import makeInventoryObjects from '../../helpers/make-inventory-objects';
moduleForComponent('model-table', 'Integration | Component | model table', {
integration: true
});
test('it renders', function(assert) {
this.set('inventoryResult', makeInventoryObjects());
this.render(hbs`{{model-table inventoryResult}}`);
assert.equal(this.$().text().trim(), '');
});
Whenever I add the comment of the import, I get this error:
: _frontendTestsHelpersMakeInventoryObjects["default"] is not a function
The main reason what I've done was failing is because I was trying to initialize the helper within the startApp and that is done only for acceptance test, not integration test.
I had to rewrite my helper to:
// ../tests/helpers/make-inventory-objects.js
export default function makeInventoryObjects() {
const inventoryObjects = [{'id': 1, 'name': 'test'}];
return inventoryObjects;
});
and then import in my test with the commented line.
Also, as a side note I missed to add in my .jshintrc my test helper if I were doing acceptance test. So, it was wrong for acceptance test as well.

Meteor 1.3 and includes: where to declare your helpers?

I'm struggling to understand Meteor 1.3's include logic.
For an app I'm trying to put together, I have in /client/main.js:
import '../imports/startup/accounts-config.js';
import '../imports/ui/body.js';
import '../imports/ui/home.js';
import '../imports/ui/map.js';
import '../imports/ui/admin.js';
...
In /imports/ui/body.js, I have (I use flow router and mainLayout is the main layout, in which all other templates are rendered):
...
Template.mainLayout.onCreated(function mainLayoutOnCreated() {
Meteor.subscribe('tasks');
Meteor.subscribe('categories');
});
...
Then I have the following function:
Template.admin.helpers({
categories() {
return Categories.find({}, { sort: { createdAt: -1 } });
},
});
If I put this function in /imports/ui/body.js, I'm able to call 'categories' in the template with name 'admin'. However, when I put this function in /imports/ui/admin.js, I get a useless exception in the javascript console:
Exception in template helper: categories#http://localho...
How is it that moving the file in which this helper is declared, while still being included in the same 'main' file, results in an exception being thrown?
You should import the desired template and the templating package at the top of your admin.js file.
import {
Template
} from 'meteor/templating';
import '.deep/admin.js';
Template.admin.helpers({
categories() {
return Categories.find({}, { sort: { createdAt: -1 } });
},
});

Register Knockout.js component viewmodel from module in typescript

My viewmodel module has several classes, so I want to register a spesific class as component's viewmodel.
And it says: Component 'filter-table': Unknown viewModel value: [object Object]
This is what I have in my viewmodel module
module FilterVM {
export class FilterViewModel {
//some code
}
class FilterTableViewModel {
}
class AttributeTableViewModel {
}
class LayerAttributeViewModel {
}
}
export = FilterVM;
And this where I am trying to register
import FilterVM = require('Scripts/App/Components/AttributeTable/ViewModels/FilterViewModel');
ko.components.register('filter-table', {
viewModel: { require: FilterVM.FilterViewModel },
template: { require: 'text!Scripts/App/Components/AttributeTable/Views/FilterTableView.html' }
});
What is wrong with that?
SOLVED
The problem was here viewModel: { require: FilterVM.FilterViewModel }
Should be viewModel: FilterVM.FilterViewModel
require('Scripts/App/Components/AttributeTable/ViewModels/FilterViewModel');
You probably need to change this into a relative path. Even though TypeScript finds it at compile time ... the runtime library may not. Use something like require('../AttributeTable/ViewModels/FilterViewModel'); etc.

Vue.js - Global Data from AJAX Call

I'm giving Vue.js a try and so far I'm loving it because it's much simpler than angular. I'm currently using vue-router and vue-resource in my single page app, which connects to an API on the back end. I think I've got things mostly working with a the primary app.js, which loads vue-router and vue-resource, and several separate components for each route.
Here's my question: How do I use props to pass global data to the child components when the data is fetched using an asynchronous AJAX call? For example, the list of users can be used in just about any child component, so I would like the primary app.js to fetch the list of users and then allow each child component to have access to that list of users. The reason I would like to have the app.js fetch the list of users is so I only have to make one AJAX call for the entire app. Is there something else I should be considering?
When I use the props in the child components right now, I only get the empty array that the users variable was initialized as, not the data that gets fetched after the AJAX call. Here is some sample code:
Simplified App.js
var Vue = require('vue');
var VueRouter = require('vue-router')
Vue.use(VueRouter);
var router = new VueRouter({
// Options
});
router.map({
'*': {
component: {
template: '<p>Not found!</p>'
}
},
'/' : require('./components/dashboard.js'),
});
Vue.use(require('vue-resource'));
var App = Vue.extend({
ready: function() {
this.fetchUsers();
},
data: function() {
return {
users: [],
};
},
methods: {
fetchUsers: function() {
this.$http.get('/api/v1/users/list', function(data, status, response) {
this.users = data;
}).error(function (data, status, request) {
// handle error
});
}
}
});
router.start(App, '#app')
Simplified app.html
<div id="app" v-cloak>
<router-view users = "{{ users }}">
</router-view>
</div>
Simplified dashboard.js
module.exports = {
component: {
ready: function() {
console.log(this.users);
},
props: ['users'],
},
};
When dashboard.js gets run, it prints an empty array to the console because that's what app.js initializes the users variable as. How can I allow dashboard.js to have access to the users variable from app.js? Thanks in advance for your help!
p.s. I don't want to use the inherit: true option because I don't want ALL the app.js variables to be made available in the child components.
I believe this is actually working and you are being misled by the asynchronous behavior of $http. Because your $http call does not complete immediately, your console.log is executing before the $http call is complete.
Try putting a watch on the component against users and put a console.log in that handler.
Like this:
module.exports = {
component: {
ready: function() {
console.log(this.users);
},
props: ['users'],
watch: {
users: {
handler: function (newValue, oldValue) {
console.log("users is now", this.users);
},
deep: true
}
}
}
};
In the new version of Vue 1.0.0+ you can simply do the following, users inside your component is automatically updated:
<div id="app" v-cloak>
<router-view :users="users"></router-view>
</div>

Generating a URL for Twitter users with Iron Router

I have users that sign in to a Meteor app with Twitter. I'd like to create a profile page route for them with Iron Router that references their Twitter screenName.
I can't work out what should replace the :slug part of the Iron Router code below (there is no property slug in my user document).
this.route('expertPage', {
path: '/profile/:slug',
data: function() { return Meteor.users.findOne({"services.twitter.screenName": this.params.slug}); }
});
First you must provide the slug as a key value pair, an object in a template helper:
userScreenName = function() {
return Meteor.user().services.twitter.screenName;
}
Template.profileLink.helpers({
slugObject: function () {
return {'slug': userScreenName()};
},
screenName: function () {
return userScreenName();
}
});
You can now supply this to the pathFor helper by using
a) with a with block
<template name="profileLink">
{{screenName}}
</template>
b) with direct use as argument
<template name="profileLink">
{{screenName}}
</template>

Categories

Resources