I know i can find examples of this but i cant put it into my code without errors... just dont know why.
I want start with set class="menu-active" to first in menu.
<li><a {{action gotoAbout}} >About</a></li>
And later when somebody click other position of menu move class="menu-active" to this position.
http://jsfiddle.net/kwladyka/LGArM/3/
And the bonus question: Do you have any remarks to make my code better?
HTML
<script type="text/x-handlebars" data-template-name="application">
{{view App.NavbarView}}
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="navbar">
<div id="menu" class="grid_12">
<ul>
<li><a {{bindAttr class="isAbout:active"}} {{action gotoAbout}} >About</a></li>
<li><a {{bindAttr class="isProjects:active"}} {{action gotoProjects}} >Projekty</a></li>
<li><a {{action gotoTechnology}} >Technologie</a></li>
<li><a {{action gotoContact}} >Kontakt</a></li>
</ul>
</div>
</script>
EMBERJS
$(function() {
console.log("### emberjs start ###");
App = Em.Application.create({
rootElement: '#emberjs-container'
});
App.ApplicationController = Em.Controller.extend();
App.ApplicationView = Em.View.extend({
templateName: 'application'
});
App.NavbarController = Em.Controller.extend({
});
App.NavbarView = Em.View.extend({
templateName: 'navbar',
});
App.AboutView = Em.View.extend({
templateName: 'about'
});
App.ProjectsView = Em.View.extend({
templateName: 'projects'
});
App.TechnologyView = Em.View.extend({
templateName: 'technology'
});
App.ContactView = Em.View.extend({
templateName: 'contact'
});
App.Router = Em.Router.extend({
enableLogging: true,
location: 'hash',
root: Em.Route.extend({
// EVENTS
gotoAbout: Ember.Route.transitionTo('about'),
gotoProjects: Ember.Route.transitionTo('projects'),
gotoTechnology: Ember.Route.transitionTo('technology'),
gotoContact: Ember.Route.transitionTo('contact'),
// STATES
about: Em.Route.extend({
route: '/',
connectOutlets: function (router, context) {
router.get('applicationController').connectOutlet('about');
}
}),
projects: Em.Route.extend({
route: '/projects',
connectOutlets: function (router, context) {
router.get('applicationController').connectOutlet('projects');
}
}),
technology: Em.Route.extend({
route: '/technology',
connectOutlets: function (router, context) {
router.get('applicationController').connectOutlet('technology');
}
}),
contact: Em.Route.extend({
route: '/contact',
connectOutlets: function (router, context) {
router.get('applicationController').connectOutlet('contact');
}
})
})
});
App.initialize();
});
Related
I am working on a small VueJS app that pulls in WordPress posts via the API. Everything works great with pagination to load more posts, however I am not too sure how I can reset the entire XHR getPosts method when you change the user ID radio field.
When you change the author ID currently, it will not reset the results. I believe it should be something in the watch: area to destroy the current page - but not too sure. Thanks!
https://codepen.io/sco/pen/aRwwGd
JS
Vue.component("posts", {
template: `
<ul>
<slot></slot>
</ul>
`
});
Vue.component("post", {
props: ["title", "excerpt", "permalink"],
template: `
<li>
<h3 v-html="title"></h3>
<div v-if="excerpt" v-html="excerpt"></div>
<a :href="permalink">Read More</a>
</li>
`
});
var App = new Vue({
el: "#app",
data: {
greeting: "Load more Posts Vue + WP REST API",
page: 0,
posts: [],
totalPages: "",
apiURL: "https://poststatus.com/wp-json/wp/v2/posts/?per_page=2",
isLoading: "",
show: true,
authors: [1, 590],
currentAuthor: ""
},
watch: {
currentAuthor: "fetchData"
},
methods: {
getPosts: function() {
var xhr = new XMLHttpRequest();
var self = this;
self.page++;
self.isLoading = "is-loading";
xhr.open(
"GET",
self.apiURL + "&page=" + self.page + "&author=" + self.currentAuthor
);
xhr.onload = function() {
self.totalPages = xhr.getResponseHeader("X-WP-TotalPages");
if (self.page == self.totalPages) {
self.show = false;
}
var newPosts = JSON.parse(xhr.responseText);
newPosts.forEach(function(element) {
self.posts.push(element);
});
self.isLoading = null;
//console.log(self.apiURL + self.page)
};
xhr.send();
}
}
});
HTML
<section id="app" class="wrapper">
<div class="container">
<div class="box">
<template v-for="author in authors">
<div class="author-toggle">
<input type="radio"
:id="author"
:value="author"
name="author"
v-model="currentAuthor">
<label :for="author">{{ author }}</label>
</div>
</template><br>
<h3 v-if="page>0">Showing Page {{page}} of {{totalPages}}</h3>
<progress v-if="page>0" class="progress" :value="page" :max="totalPages">{{page}}</progress>
<posts v-if="posts">
<post v-for="post in posts" class="post" :id="'post' + post.id" :title="post.title.rendered" :permalink="post.link" :key="post.id">
</post>
</posts>
<button :class="isLoading + ' ' +'button is-primary'" v-if="show" #click="getPosts(page)">Load Posts</button>
</div>
</div>
</section>
You can reset page, posts, and totalPages inside the watcher:
watch: {
currentAuthor() {
this.page = 0;
this.totalPages = 0;
this.posts = [];
this.getPosts();
}
}
your codepen with required changes
I show a list of items and for each item its belongs to a user. I list the item's name, description and the user who created it (by there name). I want to also have a link that goes to the user who created the item. Note: That I also link to an item's page.
Here is what I've done so far:
packages
aldeed:collection2
aldeed:simple-schema
iron:router
aldeed:autoform
useraccounts:iron-routing
accounts-password
accounts-base
useraccounts:core
zimme:active-route
todda00:friendly-slugs
reywood:publish-composite
client/items/listed_item.html
<template name="listedItem">
<a href="{{pathFor 'itemPage'}}">
{{name}}
</a>
<a href="{{pathFor 'profile'}}">
{{usernameFromId user}}
</a>
</template>
client/items/items.html
<template name="items">
<div class="items">
{{#each items}}
{{> listedItem}}
{{/each}}
</div>
</template>
client/subscriptions.js
Meteor.subscribe('items');
Meteor.subscribe('allUsernames');
Meteor.subscribe('users');
client/helpers.js
Template.items.helpers({
items: function() {
return Items.find();
},
});
Template.registerHelper("usernameFromId", function (userId) {
var user = Meteor.users.findOne({_id: this.userId});
return user.profile.name;
});
server/publications.js
Meteor.publish("items", function () {
return Items.find();
});
Meteor.publish("users", function () {
return Meteor.users.find({}, {
fields: { profile: 1 }
});
});
Meteor.publish("allUsernames", function () {
return Meteor.users.find({}, {
fields: { 'profile.name': 1, 'services.github.username': 1 }
});
});
lib/routes.js
Router.route('/items', function () {
this.render('items');
});
Router.route('/users/:_id', {
template: 'profile',
name: 'profile',
data: function() {
return Meteor.users.findOne({_id: this.params._id});
}
});
What this does though is show the items URL for the users URL, so it links to a user who doesn't exist. i.e. items/1234 = users/1234 when theres only users/1 in the system. How can I get it to link to the correct user ID?
use a link with the constructed URL
<template name="listedItem">
<a href="{{pathFor 'itemPage'}}">
{{name}}
</a>
<a href="http://yourdomain.com/users/{{user}}">
{{usernameFromId user}}
</a>
</template>
In this part:
Router.route('/users/:_id', {
template: 'profile',
name: 'profile',
data: function() {
return Meteor.users.findOne({_id: this.params._id});
}
});
you have referenced the route and created a route to a template with the name "profile" but I can't see any template with that name. Is it possible you just forgot to include it here? or that you really don't have that template?
Just making sure.
Try this:
Router.route('/users/:_id', {
template: 'profile',
name: 'profile'
}
In helper you can retrive that record id by this:
Router.current().params._id
I usually use this way:
In the template:
<div class="css-light-border">
{{title}}
</div><!-- / class light-border -->
In the router.js file:
Router.route('/document/:_id', function(){
Session.set('docid', this.params._id);
this.render('navbar', {to: "header"});
this.render('docItem', {to: "main"});
});
Basically here docid is the _id of the document which I want to display. Here is an example of how you pull from your database:
somehelper:function(){
var currentId = Session.get('docid');
var product = Products.findOne({_id:currentId});
return product;
I think it is an easy way because it uses Sessions.
I am writing my blog site with using angular.js and asp.net webapi. I did url routing with angular.js. when I click url but I get 404 not found error. How to fix this problem?
var blogSite = angular.module("blogSite", ["ngRoute"]);
blogSite.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when("post/:post", {
teplateUrl: 'blogpost.html',
controller: 'blogPostController'
})
.otherwise({
redirectTo: 'index.html'
});
}]);
blogSite.controller("mainPageController", function ($scope, $http, $routeParams) {
var url = baseUrl + "getpost";
$http.get(url)
.success(function (data, status, headers, config) {
if (data.length > 0) {
$scope.LastBlogPosts = data;
}
else {
$scope.LastBlogPosts = null;
}
})
.error(function (data, status, headers, config) {
console.log(status);
});
});
blogSite.controller("blogPostController", function ($scope, $http, $routeParams) {
$scope.TestMessage = "Test Message"
});
index.html page
div ng-controller="mainPageController">
<ul>
<li ng-repeat="blogPost in LastBlogPosts">
{{blogPost.PostTitle}}
</li>
</ul>
</div>
</div>
</div>
<div ng-view>
</div>
You anchor should be having # to restrict redirection, putting # at the start of URL will keep you in same page & will keep you in SPA
<a href="#post/{{blogPost.PostUrl}}" class="lastPostUrl mainPagePostTitle">
{{blogPost.PostTitle}}
</a>
I am fairly new to Meteor.
I have a template helper function which requires to work with data I am publishing from the server side. When the page loads, the value for profile below is undefined. But after that when I execute the same code snippet from browser's console, it works just fine. From what I understand, the template helper is being executed before the data is published. How can I wait until the data is published to run the UI helper?
Here is relevant code.
Helper Function
Template.header.helpers({
me: function() {
var user = Meteor.users.findOne(Meteor.userId());
if (user) {
return Profiles.findOne({
spid: user.profile.spid
});
}
return null;
}
});
HTML Template
<template name="header">
<header class="ui fixed inverted menu">
{{> thumb user=me}}
</header>
</template>
Thumbnail Template
<template name="thumb">
{{#with user}}
<div class="thumb">
<div class="text" style="background-color:{{color}}">
{{initials name}}
</div>
<div class="pic" style="background-image:url('{{pic}}')"></div>
</div>
{{/with}}
</template>
Publications
Meteor.publish('profiles', function() {
return Profiles.all();
});
Meteor.publish('departments', function() {
return Departments.all();
});
Meteor.publish('requestServiceIds', function() {
return Requests.getServiceIds();
});
Meteor.publish('relevantServices', function() {
return Services.getRelevant(this.userId, 5);
});
Router
Router.configure({
layoutTemplate: 'main',
waitOn: function() {
Deps.autorun(function() {
Meteor.subscribe('profiles', Partitioner.group());
Meteor.subscribe('departments', Partitioner.group());
});
}
});
Router.onBeforeAction(function() {
if (this.route.getName() === 'not-authorized') return this.next();
if (!Meteor.userId() || !Cookie.get('TKN')) {
this.render('login');
} else {
this.next();
}
});
Router.route('/', {
name: 'home',
waitOn: function() {
Deps.autorun(function() {
Meteor.subscribe('requestServiceIds', Partitioner.group());
Meteor.subscribe('relevantServices', Partitioner.group());
});
}
});
---
UPDATE 1
I updated the the router a bit. But it did not seem to have had made any difference.
Router.configure({
layoutTemplate: 'main',
waitOn: function() {
// Deps.autorun(function() {
// Meteor.subscribe('profiles', Partitioner.group());
// Meteor.subscribe('departments', Partitioner.group());
// });
return [
Meteor.subscribe('profiles', Partitioner.group()),
Meteor.subscribe('departments', Partitioner.group())
];
}
});
Router.route('/', {
name: 'home',
waitOn: function() {
// Deps.autorun(function() {
// Meteor.subscribe('requestServiceIds', Partitioner.group());
// Meteor.subscribe('relevantServices', Partitioner.group());
// });
return [
Meteor.subscribe('requestServiceIds', Partitioner.group()),
Meteor.subscribe('relevantServices', Partitioner.group())
];
}
});
Create a dumb loading template such as this one (using font awesome):
<template name="loading">
<div class="loading">
<i class="fa fa-circle-o-notch fa-4x fa-spin"></i>
</div>
</template>
And try replacing your Router.configure() part with something like this:
Router.configure({
layoutTemplate: 'main',
action: function() {
if(this.isReady()) { this.render(); } else {this.render("loading");}
},
isReady: function() {
var subs = [
Meteor.subscribe('profiles', Partitioner.group());
Meteor.subscribe('departments', Partitioner.group());
];
var ready = true;
_.each(subs, function(sub) {
if(!sub.ready())
ready = false;
});
return ready;
},
data: function() {
return {
params: this.params || {},
profiles: Profiles.find(),
departments: Departments.find()
};
}
}
});
I guess that could be achieved using waitOn, but since your way does not work, I give you a working recipe I use everyday. Code inspired from meteor Kitchen generated code.
To answer your comments:
Regarding the Action not being triggered, it might be because we tried to put in inside the Router.configure. I don't do it that way, here are some details on how I implement it.
First, I set a controller for each route inside a router.js file (where I have my Router.configure() function too. It looks like that:
Router.map(function () {
this.route("login", {path: "/login", controller: "LoginController"});
// other routes
}
Next, I create a controller that I store in the same folder than my client view template. It looks like that:
this.LoginController = RouteController.extend({
template: "Login",
yieldTemplates: {
/*YIELD_TEMPLATES*/
},
onBeforeAction: function() {
/*BEFORE_FUNCTION*/
this.next();
},
action: function() {
if(this.isReady()) { this.render(); } else { this.render("loading"); }
/*ACTION_FUNCTION*/
},
isReady: function() {
var subs = [
];
var ready = true;
_.each(subs, function(sub) {
if(!sub.ready())
ready = false;
});
return ready;
},
data: function() {
return {
params: this.params || {}
};
/*DATA_FUNCTION*/
},
onAfterAction: function() {
}
});
So this action function is working when I extend a route using a controller. Maybe it will solve your issue.
For completeness sake, here is how my Router.configure() looks like:
Router.configure({
templateNameConverter: "upperCamelCase",
routeControllerNameConverter: "upperCamelCase",
layoutTemplate: "layout",
notFoundTemplate: "notFound",
loadingTemplate: "loading",
//I removed the rest because it is useless.
});
How i can add active class to menu with angular with this case
html code
<div class="categories" ng-controller="CategoryController">
<ul class="menu">
<li ng-repeat="category in categories">
<a ng-click="sendCategory(category)">{{category.name}}</a>
</li>
</ul>
</div>
js code
myApp.factory('Categories', ['$http',
function ($http) {
return {
get: function (callback) {
$http.get('data/categories.json').success(function (data) {
callback(data);
})
}
}
}
]);
use this syntax:
<ul class="menu" ng-class="{classname: variableFromScope}">
Set this variable to true or false (to activate or disactivate your classname class) in your controller where it needed:
$scope.variableFromScope = true;
here is solution
html code
<ul class="menu">
<li ng-repeat="category in categories"><a ng-click="sendCategory(category)" ng-class="{ active: activePath=='/{{category.name}}' }">{{category.name}}</a>
</li>
</ul>
js code
`
myApp.controller('CategoryController', function ($scope, $route, $location, $http, Categories){
Categories.get(function (response) {
$scope.categories = response;
});
$scope.sendCategory = function (category) {
$location.path(category.name);
};
$scope.activePath = null;
$scope.$on('$routeChangeSuccess', function () {
$scope.activePath = $location.path();
console.log($location.path());
});
})`