first
exports.render = function(req,res){
res.render('index', {
title: 'welcome',
username : req.user ? req.user :''
});
};
I want to export object req.user to use
h2 Hello #{username.username}
h2 Hello #{username}
In Jade I can use it
div(ng-app='IndexController')
{{ #{username} | getUserData }}
but if i want to get it to angular it can't use
mainAppModule.filter('getUserData', function () {
return function (name) {
if (name)
console.log(name.username + "xxxxxxxxxxxxxxxxxxxxxxxxqqqqqqqqqq");
return 'Hellox, ';
};
});
How can i do it? how to get req.user for use in future.if there is other way to get object to use in angular please tell me.
Thank so much.
function MyCtrl($scope) {
$scope.req = {'user':'scope user'};
this.req1 = {'user':'alias user'} ;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="">
<div ng-controller="MyCtrl as myCont">
{{req.user}}
<br/>
{{myCont.req1.user}}
</div>
</div>
I am not sure what problem you are facing. You can simply use $scope or controller alias to access any variable in the view.
By Alias
<div ng-controller="MainController as main">
{{main.name.userName}}
</div>
By $scope
<div ng-controller="MainController">
{{name.userName}}
</div>
Seems you need to pass your request object to your Angular code.
What I can suggest is try to make a module which will act as a model for jade rendered objects as below:
index.jade
div(ng-controller="myController as ctrl")
h2 Title: {{ ctrl.title | myFilter }}
h2 Username: {{ ctrl.username | myFilter }}
script.
angular.module('jadeData',[])
.factory('jadeDataFactory',function(){
//model service to set objects retrieved from jade
return {
'title': "#{title}",
'username': "#{username}"
};
});
script(src="/js/app.module.js")
Once done, you can access the service model in you main module's controller
app.module.js
angular.module("myApp",['jadeData'])
.controller("myController",function(jadeDataFactory){
var that = this;
that.title = jadeDataFactory.title;
that.username = jadeDataFactory.username;
})
.filter("myFilter",function(){
return function(v){
if(v)
console.log('Inside filter value: ',v);
return v+' Modified';
}
});
This way you can inject the jadeDataFactory to any of the required controllers/services
Explanation: actually Jade is rendered in server side, and if you write {{ #{username} | getUserData }} then renderer could not get it correctly, the better way is to store it in a service model and access it in required controller.
Related
I am still pretty new to NodeJS and I am using the express and express-handlebar packages.
However, the 'if-statement' does not work properly, in fact not at all. I suppose the reason for this is that I do not use a template for the if-statement.
Using just the package 'handlebars', I would go with:
rs.readFile('files/test.hbs', 'utf-8', function(err, data)
{
var template = hbs.compile(data);
var result = template ({name: 'name', value1: 'value1', value2: 'value2'});
res.end (result);
...
}
This solution works actually.
However, I have already used express-handlebars in the entire code and would like to keep on using it. I got following code:
//I´ll receive value1 and value2 later either directly from my database or with the help of MQTT
var value1 = ' value1';
var value2 = 'value2';
var name = 'name';
var helpers={
value1:function(){return value1;},
value2:function(){return value2;},
name: function(){return name;}
}
router.get('/', function(req, res){
res.render('index', {helpers});
});
My html code looks like following:
<div>
<h1> {{value1}} </h1>
<h2> {{value2}} </h2>
{{#if name}}
<h3> hello there! </h3>
{{/if}}
</div>
value1 and value 2 are shown properly. 'hello there!' isn´t as I suppose it is not a template.
Does anyone know how I can make code work with express-handlebars?
I just answered it by myself.
The solution is:
router.get('/', function(req, res){
res.render('index', {
name,
helpers});
});
add this in server.js
const isEqual = function(a, b, opts) {
if (a == b) {
return opts.fn(this)
} else {
return opts.inverse(this)
}
}
var hbs = require('hbs');
hbs.registerHelper('if_eq', isEqual);
Somehow the computed property of a controller I'm accessing through the needs property won't work in the template. Other regular string properties work as expected. Below is my code.
To be clear, what I'm trying to achieve is to access properties of the userController and userModel in actually all of my templates/routes (some of which are computed). However, 'user' itself doesn't have a page, so that's why it's not added in the Router.map. It's just a really important class that handles everything user-related and handles access to the user-model.
I hope somebody with a bit more ember experience knows what I'm doing wrong. Or maybe got some advice on how to do this the ember-way? Any help is greatly appreciated!
PS: I tried to be as complete as possible, if I'm forgetting smt let me know, I'll add it.
App.Router.map(function() {
this.resource('signup');
this.resource('login');
this.resource('profile');
this.resource('practice');
this.resource('overview');
});
App.ApplicationRoute = Ember.Route.extend({
model: function () {
return this.store.find('user');
}
});
App.LoginRoute = Ember.Route.extend({
controllerName: 'application',
model: function () {}
});
App.UserRoute = Ember.Route.extend({
model: function () {
return this.store.find('user');
}
});
//UserController
App.UserController = Ember.ArrayController.extend({
//pagetitle property to test. Working.
pageTitle: 'Usercontroller',
//userArray property to test, but didn't work.
// Makes sense since the Arraycontroller return an array, so you'll have to use #each-helper
userArray: function(){
return this.get('content');
},
//particularUser computed property to test, but also didn't work.
// Neither did looping #each through the userArray property
particularUser : Ember.computed.filterBy('content' , 'username', 'Sunchild')
});
//LoginController
App.LoginController = Ember.ArrayController.extend({
needs: ['user'],
pageTitle: 'test-title loginController'
});
// Login template feeded into an outlet in the application template
<script type="text/x-handlebars" id="login">
<div class="content">
<form class="input-group">
<div class="input-row">
<label>Username</label>
<input type="text" placeholder="Username">
</div>
<div class="input-row">
<label>Email</label>
<input type="email" placeholder="ratchetframework#gmail.com">
</div>
<button class="btn btn-primary btn-block btn-outlined">Login</button>
</form>
<h3> test1:{{controllers.user.pageTitle}}</h3>
<h3> test2:{{controllers.user.userArray}}</h3>
{{#each user in controllers.user.particularUser}}
<div class="card_wrapper">
<p><h3>Username: {{{user.username}}}</h3><p>
<p>email: {{user.email}}</p>
</div>
{{/each}}
</div>
</script>
Without a user route in your router, the model hook in your UserRoute will never run. That means that the model of your UserController will always be empty. So the way you've set things up won't work for your use case. But, you have the same model on your ApplicationRoute, so why not use that controller instead?
App.ApplicationController = Ember.ArrayController.extend({
// Never use the `content` property, always use the `model` property, they are different
userArray: Ember.computed.alias('model'),
particularUser: function() {
// Be sure to only grab the first item, not an array with the first item in it
return this.get('userArray').filterBy('username', 'Sunchild').get('firstObject');
}.property('userArray.#each.username')
});
This is nice because your application route runs before any other route, so this data will always be available. So in your LoginController:
App.LoginController = Ember.ArrayController.extend({
needs: ['application'],
userArray: Ember.comptued.alias('controllers.application.userArray']
});
Hopefully that clears things up a bit.
I build application using web-socket and I want dynamically change view
I have code in my model:
model: function () {
var store = this.store;
var socket = new_socket();
socket.on('message', function (message) {
store.push('record',message);
});
return store.find('consultation');
}
And data successfully loading into ember store, but ember doesn't update view.
What I need to do?
For example when I use save all works fine:
var record = this.store.createRecord('record',{});
record.save()
UPDATE:
I found this solution:, but it's also not working
My controller (consultation.js):
export default Ember.ObjectController.extend({
needs: ['application'],
records: function() {
console.log(this.get('store'));
return this.get('store').filter('record', function(record) {
console.log(record);
});
}.property('records'),
Template:
{{#each item in controller.records}}
{{/each}}
Model consultation looks like this (with hasMany field):
export default DS.Model.extend({
records: DS.hasMany('record', { async: true }),
});
Second console.log is not printing,
I solved it like this
var obj = store.push('record', jsonObj.message);
this.controllerFor('consultation').get('records').pushObject(obj);
But it's looks like not good. In which way I can make auto synchronization between model and controller
You have computed properties that are dependent on themselves in your controller. Also, you really should not be pushing anything to the store, conceptually, when you receive something on your socket, your model changed, you want to capture that notion in your code, so you really should be updating the model when you get a socket message. The way I would do this would be to do something like the following:
in the router,
model: function() {
var records = this.store.find('consultation',{});
var socket = new_socket();
socket.on('message', function (message) {
records.pushObject(message);
});
return records;
}
The controller does not need to have any computed properties at all.
and in the template, the code would just be:
{{#each content}}
//do something here
{{/each}}
I'm a little confused about your use of consultation and record in the code.
I'm following the Discover Meteor book
For some reason, the content in edit_post.html doesn't show up with the {{#with post}}:
<template name="postEdit">
{{#with post}}
<form class="main">
<div class="control-group">
<label class="control-label" for="url">URL</label>
<div class="controls">
<input name="url" type="text" value="{{url}}" placeholder="Your URL"/>
</div>
</div>
.
.
.
</form>
{{/with}}
</template>
the content of post_edit.js:
Template.postEdit.helpers({
post: function() {
return Posts.findOne(Session.get('currentPostId'));
}
});
Template.postEdit.events({
'submit form': function(e) {
e.preventDefault();
var currentPostId = Session.get('currentPostId');
var postProperties = {
url: $(e.target).find('[name=url]').val(),
title: $(e.target).find('[name=title]').val()
}
Posts.update(currentPostId, {$set: postProperties}, function(error) {
if (error) {
// display the error to the user
alert(error.reason);
} else {
Router.go('postPage', {_id: currentPostId});
}
});
},
'click .delete': function(e) {
e.preventDefault();
.
.
.
}
}
});
route.js:
this.route('postEdit', {
path: '/posts/:_id/edit',
data: function() { return Posts.findOne(this.params._id); }
});
The template shows up if I remove the {{#with post}}.
I'm not sure if this is an error in the book, or whether I'm doing something wrong. I'm a Meteor beginner so I have no clue.
Any suggestion to fix this?
The template helper post calls a Session variable that is never set so I think that findOne() returns a falsy value. So {{#with post}} is correctly keeping the template from displaying. Without the {{#with post}} your template is able to display a post from the data function in the router. You are calling findOne() looking for the same data twice but either method will work to get the data you want for the template.
If you want to use {{#with}} you can change your route.js to:
this.route('postEdit', {
path: '/posts/:_id/edit',
before: function() { Session.set( "currentPostId", this.params._id ); }
});
I'm looking at the code from the book and I cannot see the with block you are referring to.
In fact, it should not be there because the data context of the template is already set by the router.
Your template helper (post) is not supposed to be there since it is both unnecessary and in fact there is no already set session variable so your get returns null as expected.
Just delete your helper and the with block and let iron router provide the data context as it already does.
I was watching Ember screencasts & stumbled upon autocomplete-widget. I tried to implement something like that but it's not working it seems.
I am getting data using $.getJSON and I want to filter that using textbox.
Here's what I have tried,
App = Ember.Application.create();
App.Model = Ember.Object.extend({
});
App.IndexRoute = Ember.Route.extend({
redirect : function() {
this.transitionTo('users');
}
});
App.UsersController = Ember.ArrayController.extend({
filteredContent : function() {
var searchText = this.get('searchText'), regex = new RegExp(searchText, 'i');
return this.get('model').filter(function(item) {
return regex.test(item.name);
});
}.property('searchText', 'model')
});
App.Users = App.Model.extend({
id : "",
name : ""
});
App.UsersRoute = Ember.Route.extend({
model : function() {
return App.Users.findAll();
},
setupController : function(controller, model) {
controller.set('model', model);
}
});
App.Users.reopenClass({
findAll : function() {
return $.getJSON("user.php", function(data) {
return data.map(function(row) {
return App.Users.create(row);
});
});
}
});
App.Router.map(function() {
this.resource("users", {
path : "/users"
});
});
Here's my HTML,
<body>
<script type="text/x-handlebars" data-template-name="users">
{{view Ember.TextField value=searchText}}
<button {{action last}}>filter</button>
<button {{action refresh}}>refresh</button>
{{#each item in content }}
<tr><td>
<p> {{item.name}}</p>
</td></tr>
{{/each}}
</script>
<script type="text/x-handlebars">
<h1>Application Template</h1>
{{outlet}}
</script>
</body>
I am actually stuck on where should I make changes, I just need some pointers.
Update: Even though I am getting the expected outcome but I am getting
Uncaught TypeError: Cannot read property 'selectedIndex' of undefined
Any idea why I am getting this?
I think that you are returning before the promise from $.getJSON has been fulfilled. Try changing your App.User.findAll so that it returns the results from inside the success callback. So specifically, your findAll implementation might look like:
App.Users.reopenClass({
findAll: function() {
return $.getJSON("https://api.github.com/users/rjackson/repos", function(data) {
return data.map(function(row) { return App.Users.create(row); });
});
}
});
Also, I do not believe that you need to manually create the ArrayProxy object. Return an array from your routes model hook should suffice.
I made some additional tweaks to your original (including using a sample JSON endpoint) here: http://jsbin.com/oWUBeMu/3/edit
Updated: 2013/08/30
The selectedIndex error is being caused by the HTML comments in your 'users' template. Handlebars comments should be {{! }} or {{!-- --}}. The html comments were causing some bizare escaping when parsing the template that caused it not to be able to bind to the properties properly.