I'm trying to reverse a model's output in ember. It was suggested (via IRC channel) that I use a computed property, but I am having a tough time figuring out how to do this.
I'm trying to do this in the controller. Any help would be appreciated, as I am pretty new to ember.
controllers/comments.js
export default Ember.Controller.extend({
model: 'comment',
reverse: function(){
return this.get('model').toArray().reverse();
}.property('model.#each')
});
comments.hbs
{{#each model as |item|}}
<div class="each__comment">
<div class="comment__image">
<img src="{{ item.img_src }}">
</div>
<div class="comment__text">
<h2 class="comment__author">{{item.full_name}}</h2>
<h3 class="comment__title">{{item.title}}</h3>
<p class="comment__description">{{item.description}} </p>
<p class="comment__date">{{ item.date_posted }}</p>
</div>
</div>
{{/each}}
routes/comments.js
export default Ember.Route.extend({
model: function() {
return this.store.find('comment');
},
actions: {
createComment: function() {
var title = this.controller.get('newComment');
if (title && !title.trim()) {
this.set('newComment', '');
return;
}
var comment = this.store.createRecord('comment', {
description: title
});
this.controller.set('newComment', '');
// Save the new model
comment.save();
}
}
});
models/comment.js
var Comment = DS.Model.extend({
img_src: DS.attr('string', {
defaultValue: '/assets/images/user-img-4.png'
}),
full_name: DS.attr('string', {
defaultValue: 'Nick Beattie'
}),
title: DS.attr('string', {
defaultValue: 'Developer'
}),
description: DS.attr('string', {
defaultValue: 'description duh'
}),
date_posted: DS.attr('string', {
defaultValue: 'Tues Nov 17th'
})
});
Comment.reopenClass({
FIXTURES: [
{
"id": "1",
"img_src": "/assets/images/user-img-1.png",
"full_name": "Tony Jackson",
"title": "Product Designer",
"description": "Morbi at augue eu felis cursus feugiat. Pellentesque a dui ut magna tristique imperdiet. Donec nec rutrum purus. Quisque id nibh metus. Proin condimentum non ipsum at sagittis. Suspendisse potenti.",
"date_posted": "Tues Apr 10th"
},
{
"id": "2",
"img_src": "/assets/images/user-img-2.png",
"full_name": "Laura Malroy",
"title": "Strategist",
"description": "Proin egestas turpis nec orci vulputate accumsan. Nullam gravida ultricies feugiat. Praesent molestie pulvinar egestas.",
"date_posted": "Sat May 14th"
},
{
"id": "3",
"img_src": "/assets/images/user-img-3.png",
"full_name": "Nicole Emsley",
"title": "Illustrator",
"description": "Etiam sed cursus mi. Morbi neque elit, ullamcorper et justo ut, pharetra egestas metus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Morbi magna dolor, pretium eget convallis ac, faucibus quis elit. Pellentesque vehicula vestibulum ante in bibendum. Nam tristique nec mi sit amet semper.",
"date_posted": "Mon Jun 9th"
}
]
});
export default Comment;
You are practically there, just switch to using the computed property in the template instead of the model property.
{{#each reverse as |item|}}
<div class="each__comment">
<div class="comment__image">
<img src="{{ item.img_src }}">
</div>
<div class="comment__text">
<h2 class="comment__author">{{item.full_name}}</h2>
<h3 class="comment__title">{{item.title}}</h3>
<p class="comment__description">{{item.description}} </p>
<p class="comment__date">{{ item.date_posted }}</p>
</div>
</div>
{{/each}}
Also you don't need to define the model property in your controller, it's just going to get overwritten by the route. Additionally, the #each notation is generally used for watching a particular property on each item, if you just want to see if the collection grows or shrinks you can watch length or [].
export default Ember.Controller.extend({
reverse: function(){
return this.get('model').toArray().reverse();
}.property('model.[]')
});
Example: http://emberjs.jsbin.com/rucojiyemu/1/edit?html,js,output
Related
I am writing my backend using DRF and using VueJS frontend templates. In the admin panel I use Ckeditor to edit textfield.
class ArticleModelForm(forms.ModelForm):
content = forms.CharField(widget=CKEditorUploadingWidget)
class Meta:
model=Article
fields = [ "title", "slug" "published_at"]
While rendering a post TextField I can not use template filters to render correctly, so text seems ruined. I have tried lots of things but no success yet.
<template>
<div>
<div class="container negative-margin-top150">
<div class="col col-xl-8 m-auto col-lg-12 col-md-12 col-sm-12 col-12">
<div class="ui-block">
<!-- Single Post -->
<article class="hentry blog-post single-post single-post-v1">
<div class="post-content-wrap">
<div class="post-content" >
<p class="post-paragraph">
{{article.content}}
</p>
<p>{{content}}</p>
</div>
</div>
</article>
<!-- ... end Single Post -->
</div>
</div>
</div>
</div>
</template>
and my script is below
<script>
import axios from 'axios';
export default {
name: "Article",
props: {
slug: {
type: String,
required: true
}
},
data() {
return {
article: {},
content: `${content}`,
}
},
methods: {
setPageTitle(title) {
document.title = title;
},
setRequestUser() {
this.requestUser = window.localStorage.getItem("username");
},
getArticle(slug) {
axios.get(`http://localhost:8000/api/articles/${this.slug}`)
.then(response => {
this.article = response.data;
this.setPageTitle(response.data.title);
this.content = window.content;
});
}
},
created() {
this.getArticle();
this.setRequestUser();
},
};
</script>
Now in the browser my text is rendered with template tags
<h3>The standard Lorem Ipsum passage, used since the 1500s</h3>
<p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
Anybody here who can point me in the right direction?
You need to use v-html attribute to render raw conent.
https://v2.vuejs.org/v2/guide/syntax.html
I'm looking for a proper workaround for that bootstrap problem.
When we use the following css hack from some other stack overflow questions to make sure the modal doesn't go higher than the screen and at the same time having a vertical scrollbar for the body. This actually works just fine and is the desired behavior.
.modal-body {
max-height: calc(100vh - 210px);
overflow-y: auto;
}
the popover inside the modal-body pops under the header and/or footer. See the following fiddle for an example : https://jsfiddle.net/2qeo99k3/4/
or the code bellow. I didn't find any answers on this specific problem after searching or clicking questions that may already have my answer. Changing the popover z-index has no effect.
<style>
.modal-body {
max-height: calc(100vh - 210px);
overflow-y: auto;
}
</style>
<script type="text/javascript">
$(document).ready(function () {
$('[data-toggle="popover"]').popover();
});
</script>
<div style="padding:12px">
This example have a popover at the top and one at the bottom. Click them to see that the popup shows under the header or the footer of the modal when using the css for the modal-body
<br>
<br>
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModalLong">
Launch demo modal
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModalLong" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<a class="btn btn-primary" data-toggle="popover" data-html="true" data-placement="top" data-content="This is one line<br>This is another line<br>This is another line">Show bootstrap popover top</a>
<br><br>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis lobortis enim in eros tincidunt, non finibus velit rutrum. Donec ultricies arcu sed tellus vestibulum, ornare rutrum massa ultrices. Sed sem metus, mattis ut dolor ut, interdum mattis nisi. Suspendisse auctor libero sit amet faucibus iaculis. Curabitur in eros dictum, auctor nulla a, aliquet est. Aenean vitae aliquet sem. Curabitur in lobortis justo.
Nullam quis purus quis ex venenatis rutrum. Morbi mattis leo nisi, a vehicula risus venenatis egestas. Suspendisse gravida eu nisl mattis rutrum. In mi metus, hendrerit a velit eu, mollis facilisis lorem. Quisque est nibh, volutpat nec ante ac, dictum congue tortor. Maecenas dui magna, vulputate at nisi a, pretium hendrerit turpis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean maximus magna in erat hendrerit, non placerat lorem vestibulum. Suspendisse ut nulla at ante fermentum sollicitudin. Proin tincidunt tempus urna at imperdiet. Nullam eget urna justo. Quisque nec est ante.
Nullam auctor dictum metus, in congue sapien eleifend eget. Quisque facilisis tortor in lorem commodo, eget vulputate diam condimentum. Proin ultrices orci ut feugiat pellentesque. Proin vitae malesuada erat. Quisque lacinia odio accumsan, sollicitudin turpis vitae, efficitur libero. Quisque bibendum, nibh sit amet imperdiet efficitur, metus turpis pharetra dolor, quis hendrerit nisi arcu sed mauris. In quis felis tincidunt, blandit libero et, scelerisque quam. Ut in magna vestibulum, pellentesque neque eu, porta justo. Quisque id justo consequat, suscipit neque non, porta dui.
Suspendisse potenti. Curabitur convallis varius lacus a eleifend. Suspendisse et finibus neque. Vivamus efficitur, tortor at malesuada faucibus, sem ipsum scelerisque nisl, vitae imperdiet nunc ex at ex. Vivamus suscipit volutpat porta. Nunc nisl mauris, blandit in molestie in, sollicitudin id lacus. Cras tempor, tortor non placerat cursus, purus nunc fermentum felis, vitae cursus lorem nisi vel enim. Sed quis maximus elit. Suspendisse ullamcorper, nulla et gravida porta, mi lorem sollicitudin leo, id consectetur velit nunc non libero. Nullam nec felis vel lorem feugiat placerat. Donec id elit sed nibh volutpat faucibus sed iaculis purus. Suspendisse vulputate, nibh sed scelerisque porta, diam felis condimentum massa, a convallis nulla libero id erat. Phasellus vestibulum lectus imperdiet, porta nibh at, sagittis massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean fermentum tincidunt tortor, at lacinia urna gravida eget.
<br><br>
<a class="btn btn-primary" data-toggle="popover" data-html="true" data-placement="bottom" data-content="This is one line<br>This is another line<br>This is another line">Show bootstrap popover bottom</a>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
Wow it was fast. After searching even more I found this :
$('[data-toggle="popover"]').popover({ container: 'body' });
It solves the problem
I try to understand how Ember works and I have an issue I can't understand. I am following a tutorial (guides.emberjs.com/v1.10.0/) and I don't understand why I only see an element when I go on a page when I click (and doesn't work with a direct link).
I think some screenshots will be helpful to understand my issue.
This is what I have when I visit "index.html#/posts/1". No article is displayed.
http://i.stack.imgur.com/qzwlq.png
This is what I have when I visit "index.html#/posts" and then click on Rails is Omakase on the left. An article is displayed whereas the link is on my browser is "index.html#/posts/1" (and when I refresh nothing is displayed).
http://i.stack.imgur.com/YpmzX.png
This is my index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Blog tuto</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/2.3.2/css/bootstrap-combined.no-icons.min.css">
</head>
<body>
<script type="text/x-handlebars">
<div class="navbar">
<div class="navbar-inner">
<a class="brand" href="#">Bloggr</a>
<ul class="nav">
<li>{{#link-to "posts.index"}}Posts{{/link-to}}</li>
<li>{{#link-to "about"}}About{{/link-to}}</li>
</ul>
</div>
</div>
{{outlet}}
</script>
<script type="text/x-handlebars" id="about">
<p>
Lorem ipsum about
</p>
</script>
<script type="text/x-handlebars" id="posts">
<div class="container-fluid">
<div class="row-fluid">
<div class="span4">
<table class="table">
<thead>
<tr><th>Recent Posts</th></tr>
</thead>
{{#each post in model}}
<tr>
{{#link-to "posts.post" post}}
<td>{{post.title}} <small class="muted">by {{post.author}}</small></td>
{{/link-to}}
</tr>
{{/each}}
</table>
</div>
<div class="span8">
{{outlet}}
</div>
</div>
</div>
</script>
<script type="text/x-handlebars" id="posts/post">
{{#if isEditing}}
{{partial "post/edit"}}
<button {{action "doneEditing"}}>Done</button>
{{else}}
<button {{action "edit"}}>Edit</button>
{{/if}}
<h1>{{title}}</h1>
<h2><small class="muted">by {{author}}</small></h2>
<hr>
<div class="intro">
{{exerpt}}
</div>
<div class="below-the-fold">
{{body}}
</div>
</script>
<script type="text/x-handlebars" id="post/edit">
<p>{{input type="text" value=title}}</p>
<p>{{input type="text" value=exerpt}}</p>
<p>{{textarea value=body}}</p>
</script>
<script src="../js/libs/jquery.min.js"></script>
<script src="../js/libs/handlebars.js"></script>
<script src="../js/libs/ember.js"></script>
<script src="../js/libs/ember-data.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/showdown/0.3.1/showdown.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.1.0/moment.min.js"></script>
<script src="app.js"></script>
</body>
</html>
And app.js
App = Ember.Application.create();
App.Router.map(function() {
this.route('about');
this.resource('posts', function () {
this.route('post', {path: ':post_id'});
});
});
App.PostsRoute = Ember.Route.extend({
model: function () {
return posts;
}
});
App.PostsPostRoute = Ember.Route.extend({
model: function (params) {
return posts.findBy('id', params.post_id);
}
});
App.PostsPostController = Ember.ObjectController.extend({
isEditing: false,
actions: {
edit: function () {
this.set('isEditing', true);
},
doneEditing: function () {
this.set('isEditing', false);
}
}
});
var posts = [{
id: 1,
title: "Rails is Omakase",
author: "mc100s",
date: new Date('08-06-2015'),
exerpt: "Lorem ipsum dolor sit amet",
body: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}, {
id: 2,
title: "The Parley Letter",
author: "mc100s",
date: new Date('08-06-2015'),
exerpt: "Duis aute irure dolor in reprehenderit",
body: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}];
Thank you for your help
When you click link, model is passed directly to the route and route's model hook is not fired, so you see article. When you reload route model hook is fired and something goes wrong.
Make string id, because params.post_id is String.
findBy is Ember.Array method. http://emberjs.com/api/classes/Ember.Array.html#method_findBy
I would try:
var posts = Ember.A([{
// as is
}]);
Next change ObjectController to Controller (ObjectController is deprecated) and use {{model.title}} instead of {{title}} in template:
<script type="text/x-handlebars" id="posts/post">
{{#if isEditing}}
{{partial "post/edit"}}
<button {{action "doneEditing"}}>Done</button>
{{else}}
<button {{action "edit"}}>Edit</button>
{{/if}}
<h1>{{model.title}}</h1>
<h2><small class="muted">by {{model.author}}</small></h2>
<hr>
<div class="intro">
{{model.exerpt}}
</div>
<div class="below-the-fold">
{{model.body}}
</div>
working jsbin here: http://jsbin.com/pozabixeka/edit?html,js,output
I am trying to use cflayout to create an accordion control on ColdFusion 11. Below is the code I am using:
<cflayout name="outerlayout" type="accordion" titlecollapse="true" width="150px">
<cflayoutarea name="area1" collapsible="true" title="acc1">
<h3>Area 1</h3>
<ul><li>sdfgsdfg</li><li>sdfgsdf</li></ul>
</cflayoutarea>
<cflayoutarea name="area2" collapsible="true" title="acc2">
<h3>Area 2</h3>
<ul><li>sdfgsdfg</li><li>sdfgsdf</li></ul>
<ul><li>sdfgsdfg</li><li>sdfgsdf</li></ul>
<ul><li>sdfgsdfg</li><li>sdfgsdf</li></ul>
</cflayoutarea>
</cflayout>
I have the following issues with the code:
1. It displays same height for each accordion irrespective of their content.
2. Unordered list doesn't get displayed as usual.
3. I want all the accordions to be initially collapsed. I am not able to accomplish it.
Note: I know it's not wise to use cflayout of the ColdFusion. But anyway I want to use it.
I finally decided to switch to jQuery solution as the cflayout solution of ColdFusion seems to be very buggy. This is how I achieved my requirements using jquery.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jQuery UI Accordion - Collapse content</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script>
$(function() {
$( "#accordion" ).accordion({
active: false,
collapsible: true,
heightStyle: "content"
});
$("#accordion>h3>a").click(function(){
var loc = $(this).prop("href");
window.open(loc, '_blank');
})
});
</script>
</head>
<body>
<div id="accordion">
<h3>Section 1</h3>
<div>
</div>
<h3>Section 2</h3>
<div>
<p>Sed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet purus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor velit, faucibus interdum tellus libero ac justo. Vivamus non quam. In suscipit faucibus urna. </p>
</div>
<h3>Section 3</h3>
<div>
<p>Nam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis. Phasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero ac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis lacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui. </p>
<ul>
<li>List item one</li>
<li>List item two</li>
<li>List item three</li>
</ul>
</div>
<h3>Section 4</h3>
<div>
<p>Cras dictum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia mauris vel est. </p><p>Suspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </p>
</div>
</div>
</body>
</html>
To solve my first issue we need to set heightStyle option to "content". It ensures that the height of each accordion element is a according to content of its elements.
The jQuery accordion has no issues with unordered list.
Finally to make all the accordions collapsed initially, we just need to set active to false.
One more thing. I noted that jQuery accordion loads faster than the Coldfusion's one. Thanks Adam Cameron & Scott Stroz for pushing me to go for jQuery solution.
To answer your Issue #1:
The code for cflayout.js on ColdFusion 11 has the height for all accordion tabs hardcoded to 600. This results in either scrollbars or large blank spaces in each tab.
Edit the code at c:\ColdFusion11\cfusion\wwwroot\CFIDE\scripts\ajax\package\cflayout.js, and delete Line 430 which reads:
_85e.height=600;
You will need to flush the template and component caches after editing this code (in the Caching section of ColdFusion Administrator).
At the console.log line in the render method below, it shows that this.member instance is exactly what it should be. So member object is good. I've spit out the string in tpl and it's what it should be. So what's causing the error in topic title?
Additional info: This view is a subview rendered by parent. I'm using Backbone.Subviews.
Thanks a lot for your help. I'm spinning my wheels :-/
Here is my code...
EDIT: Changed member object attrib references and now it works...
Template...
<div class="wrap-profile container">
<div class="profile-pic">
<div class="pic">
<img src="<%= pathUploads %><%= member.photo_profile %>" width="400" height="600" id="<%= member.id %>" class="photo-img">
</div>
</div>
<div class="profile-info">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent consectetur urna nec erat pretium tempus.
</div>
<div>
Morbi nec arcu at leo lobortis egestas. Phasellus sagittis neque dolor, ut congue lorem egestas id.m laoreet, vitae tristique lorem sollicitudin.
</div>
<div>
In vel libero eget enim rhoncus suscipit. Nunc tristique in nisi eget bibendum. Mauris et pulvinar orci.
</div>
<div>
Quisque eget sem id dolor tempus dictum. Pellentesque luctus scelerisque lacinia.
</div>
<div>
Sed gravida rutrum bibendum. Aenean condimentum eu dui nec adipiscing. Duis sagittis pharetra enim.
</div>
</div>
</div>
The view js...
// ProfileView.js
define( function(require) {
"use strict";
var $ = require('jquery'),
_ = require('underscore'),
Backbone = require('backbone'),
Helper = require('helper'),
tpl = require('text!templates/profilePicTemplate.html'),
template = _.template(tpl);
return Backbone.View.extend({
el: $("#profile"),
initialize: function(member) {
var self = this;
this.member = member;
},
render: function() {
var data = {
pathUploads: Helper.global.pathUploads,
member: this.member
};
console.log(this.member);
this.$el.html(template(data));
return this;
},
destroy: function() {
template = null
this.member = null;
}
});
});
The evidence points quite directly at this.member being a plain old javascript object instead of an instance of a Backbone.Model subclass. You seem to be aware of this, so I think it's a case of "no really, hear us now and believe us later". To test this theory, swap in this snippet.
var data = {
pathUploads: Helper.global.pathUploads,
member: new Backbone.Model(this.member)
};
If that fixes it, the theory holds.
(Aside...)
For what it's worth, making your template require a backbone model instance instead of plain data is probably inferior, so consider just having your template do <%= member.photo_profile %> instead so it doesn't care where the data comes from. This also makes it easier to use the presenter design pattern. You can use member.toJSON() in your view to get at the plain data attributes to pass in to the template.