Inserting view in template in ember.js - javascript

Hello there i am following "lets learn ember" by José Mota in tuts premium. I am stuck in a very strange situation.
I am at 9th video in the series where i am learning to create list view items and inserting that view in application template. I exactly did what author did in the video, however the result doesn't show up in the screen. But in console the obejct is successfully added.
I am creating a flash message view, whenever user add certain message the flash message should display at the top of the screen with fade in effect.
I have basically an alert view that handles fadein and out of the message, App.flashController controller which in turn extended from App.FlashController, which extends Ember.ArrayController, and App.FlashListView view.
Here is my code
flash.js controller
App.FlashController = Ember.ArrayController.extend();
App.flashController = App.FlashController.create({content: Ember.A()});
FlashListView code:
App.FlashListView = Ember.CollectionView.extend({
itemViewClass: "App.AlertView"
, contentBindings: "App.flashController"
});
Alert view code
App.AlertView = Ember.View.extend({
templateName: "_alert"
, tagName: "div"
, classNameBindings: ["defaultClass", "kind"]
, defaultClass: "alert-box"
, kind: null
, click: function(){
this.$().fadeOut(300, function(){ this.remove();});
}
, didInsertElement: function(){
this.$().hide().fadeIn(300);
}
});
here is the order of loading of the files
<script src="js/app.js"></script>
<script src="js/route/route.js"></script>
<script src="js/controllers/bookmarks_controller.js"></script>
<script src="js/controllers/bookmark_controller.js"></script>
<script src="js/views/alert.js"></script>
<script src="js/views/flash_list.js"></script>
<script src="js/controllers/flash.js"></script>
And this is where the flash message should be displayed
<script type="text/x-handlebars" data-template-name="application">
<div>
<nav class="top-bar" data-options="is_hover:true">
<ul class="title-area">
<li class="name">
<h1>My Ember Site </h1>
</li>
</ul>
<section class="top-bar-section">
<ul class="right">
<li class="name">{{#linkTo "index"}}Home{{/linkTo}}</li>
<li>{{#linkTo "about"}}About{{/linkTo}}</li>
<li>{{#linkTo "about.team"}}About Team{{/linkTo}}</li>
<li>{{#linkTo "about.kshitiz"}}About Kshitiz{{/linkTo}}</li>
<li>{{#linkTo "bookmarks"}}Bookmarks{{/linkTo}}</li>
</ul>
</section>
</nav>
</div>
<div class="container">
<div class="row">
{{outlet}}
{{view App.FlashListView}}
</div>
</div>
</script>
_alert template code:
<script type="text/x-handlebars" data-template-name="_alert">
{{view.content.message}}
</script>
in browser when I write this command
App.flashController.pushObject(Ember.Object.create({message:"Hello!"}))
a class was returned
Class {message: "Hello!", constructor: function, toString: function,
reopen: function, init: function…}
But it doesnt show up in screen as in tutorial.
I have no idea what went wrong and i am completely new to this ember.js world.

There is a possible typo in App.FlashListView, should be singular contentBinding not plural contentBindings
App.FlashListView = Ember.CollectionView.extend({
itemViewClass: "App.AlertView"
, contentBinding: "App.flashController"
});

Related

Change div content dynamically on ng-click AngularJS

I want to display some data and tables in the content div which depends on which category you choose on the left hand side navigation.
So if I change the category also the displayed content of the content div should change.
Here is my code on Plunkr.
But it seems that not even this simple example is working.
So I have two Questions:
1.) How can I fix this example code to run ?
But more important:
2.) Is there a better way to change the content div when you change the category ?
I removed 'this' elements from code and also changed ng-view to ng-show.
<div>
<div ng-show="showApple">{{content}}</div>
<div ng-show="showBanana">{{content}}</div>
<div ng-show="showOrange">{{content}}</div>
</div>
There was something wrong with that you named your div class "content" so I removed that also.
I am sure it isn't a perfect solution but now it works.
link to plnkr
To be honest your best bet is to use $states/views. With a data-ui-view on the content div and a data-ui-sref link on the button on your menu, you can easily switch out content. Take a look at the ui-router page to get a better understanding of it. With templates for each 'view' that your menu will click to, your code will not just be much easier to manage, but probably more understandable.
You can use ng-include to show your contents but you have to keep them in seperate files e.g contentForApple, contentForBanana and contentForOrange.
Here I can show you a little change in your div
<div class="content">
<div ng-show="MainCtrl.showApple" ng-include ="'contentForApple.html'"></div>
<div ng-show="MainCtrl.showBanana" ng-include = "'contentForBanana.html'"></div>
<div ng-show="MainCtrl.showOrange" ng-include = "'contentForOrange.html'"></div>
</div>
Hope this help you. Take one json array for category and data and get details of json data which index is clicked
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body ng-app="myApp" ng-controller="MyController">
<div class="container">
<div class="row">
<div class="col-lg-3">
<ANY ng-repeat="x in category" ng-click="getData($index)">
{{x.category}}<br>
</ANY>
</div>
<div class="col-lg-6">
{{data}}
</div>
</div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('MyController', function ($scope)
{
$scope.data = '';
$scope.category = [{category:'Apple',data:'Apple Data'},{category:'Banana',data:'Banana Data'},{category:'Orange',data:'Orange Data'}];
$scope.getData = function(index)
{
$scope.data = $scope.category[index]['data'];
}
});
</script>
</body>
</html>
I did it with simple ngif
1) Keep an Index of Page which needs to be is loaded now
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.pageIndex = 0;
/*
* Updates current Page index
*/
$scope.changeIndex= function(indexToChange){
$scope.pageIndex = indexToChange;
}
});
2) Load content based on selected index
<body ng-controller="MainCtrl">
<div class="mainframe">
<div class="navigation">
<ul class="list-group">
<li class="list-group-item" ng-click="changeIndex(0)">Home<span class="status-icon"></span></li>
<li class="list-group-item" ng-click="changeIndex(1)">Sign Up<span class="status-icon"></span></li>
<li class="list-group-item" ng-click="changeIndex(2)">About<span class="status-icon"></span></li>
</ul>
</div>
<div class="content">
<div ng-if="pageIndex == 0" ng-include ="'Home.html'"></div>
<div ng-if="pageIndex == 1" ng-include = "'SignUp.html'"></div>
<div ng-if="pageIndex == 2" ng-include = "'About.html'"></div>
</div>
</div>
Final Result:
https://embed.plnkr.co/ic0eY2vwiOnChN2ahrEt/

EmberJS passing variable to the layout

I have a really basic test app. It has 2 pages an empty index and a login form on an other page. And I would like to know how can I pass variables to the layout which is the same on every page (user name/status for display it and display login/logout by status).
Or the best solution could be something like this: pass a user model to the AppController which is available from anywhere (like login page or login modals) and If I change and save the data the site template is just changing by the passed variables.
I was trying to find a good way, I find a few ones but none of them was working :( If you know a working way please share me or show me what is the solution.
Here is my code: the JS I have:
App = Ember.Application.create();
App.ApplicationController = Ember.Controller.extend({});
/* *** Index *** */
App.IndexView = Ember.View.extend({
layoutName: 'app_view'
});
App.IndexController = Ember.Controller.extend({
});
/* *** LOGIN *** */
App.Router.map(function () {
this.resource("login");
});
App.LoginView = Ember.View.extend({
layoutName: 'app_view'
});
App.LoginController = Ember.Controller.extend({
login: function() {
// blah blah
}
});
Layout template:
<script type="text/x-handlebars" data-template-name="app_view">
<header id="site">
{{#link-to "index"}}Index{{/link-to}}
{{#link-to "login"}}Login{{/link-to}}
{{variablaWhatIWant}}
</header>
<hr />
<section id="content">
{{yield}}
</section>
<hr />
<footer id="main">
Footer
</footer>
</script>
2 view templates:
<script type="text/x-handlebars" data-template-name="index">
Hello INDEX page!
</script>
<script type="text/x-handlebars" data-template-name="login">
<form class="form-horizontal" {{action "login" on="submit"}}>
<div class="control-group">
Username: {{input value=username type="text"}}
</div>
<div class="control-group">
Password {{input value=password type="password"}}
</div>
<button type="submit" class="btn">Log in!</button>
</form>
</script>
Thank you very much! :)
You have the right idea, see managing dependancies between controllers http://emberjs.com/guides/controllers/dependencies-between-controllers
just set the needs property, and you can access that controller from any other
App.LoginController = Ember.Controller.extend({
needs: ['application'],
login: function() {
this.authenticate(this.get('username'), this.get('password')).then(function(user) {
this.set('controllers.application.user', user);
},
function(err) {
//auth err
}
}
});

Output in multiple parts of the page

index.html:
<div id="section_a">
<script type="text/x-handlebars" data-template-name="index">
First value: {{input type="text" value=one}}<br>
Second value: {{input type="text" value=two}}<br>
Result: {{result}}
</script>
</div>
<div id="section_b">
<!-- Display {{result}} here aswell -->
</div>
application.js
App.IndexController = Ember.ObjectController.extend({
one: 0,
two: 0,
result: function() {
return this.get('one') + this.get('two');
}.property('one', 'two')
});
I have a section of a page where I have some Ember interactions - a user inputs some values and a calculated result is displayed.
I now want to have the calculated result displayed in another part of the page that is outside the defined template, how would I accomplish this?
You could bind that property to the application controller and then use it anywhere you want in the application. For example:
App.ApplicationController = Ember.ObjectController.extend({
needs: ['index'],
indexResult: Ember.computed.alias('controllers.index.result')
});
Now you can use it anywhere within the application you want. Just tell the outlet's controller to need the application controller, then call that property in the template. Like so:
App.FooController = Ember.ArrayController.extend({
needs: ['application'],
//...
});
In the Foo template:
{{controllers.application.indexResult}}
Or, if you are within the application scope you can just do:
{{indexResult}}
One simple and straight forward solution would be:
<script type="text/x-handlebars" data-template-name="index">
<div id="section_a">
First value: {{input type="text" value=one}}<br>
Second value: {{input type="text" value=two}}<br>
Result: {{result}}
</div>
<div id="section_b">
<!-- Display {{result}} here aswell -->
</div>
</script>
You can also set up another outlet that can be used to display the "result". You can read more about using outlets in the Ember.js Guides at http://emberjs.com/guides/routing/rendering-a-template/

emberjs append works but raises Assertion Failed error

I'm new to ember I am trying to append a template to another and it seems to work but it raises an error, can you please explain why?
The error:
Assertion failed: You cannot append to an existing Ember.View. Consider using Ember.ContainerView instead
This is the code in app.js
App.NewStickie = Ember.View.extend({
click: function(evt){
var stickie = Ember.View.create({
templateName: 'stickie',
content: 'write your notes here'
});
stickie.appendTo('#stickies');
}
});
These are the contents of index.html
<script type="text/x-handlebars">
{{#view App.NewStickie}}
<button type="button" class="btn btn-success">
New
</button>
{{/view}}
{{outlet}}
</script>
<script type="text/x-handlebars" id="index">
<div id="stickies">
{{#each item in model}}
<div class="stickie" contenteditable="true">
{{#view App.DeleteStickie}}
<span class="glyphicon glyphicon-trash"></span>
{{/view}}
<div contenteditable="true">
{{item.content}}
</div>
</div>
{{/each}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="stickie">
<div class="stickie">
{{#view App.DeleteStickie}}
<span class="glyphicon glyphicon-trash"></span>
{{/view}}
<div contenteditable="true">
{{view.content}}
</div>
</div>
</script>
Each view in ember have a template, for example:
foo_view.js
App.FooView = Ember.View.extend({
templateName: 'foo'
})
foo template
<script type="text/x-handlebars" data-template-name="index">
<div id=myFooView>Foo</div>
</script>
You are trying to insert a view inside of other in that way:
App.BarView.create().appendTo('#myFooView')
This isn't allowed. You can use the {{view}} handlebars helper to render a view inside other like that:
foo template
<script type="text/x-handlebars" data-template-name="index">
<div id=myFooView>
Foo
{{view App.BarView}}
</div>
</script>
But I think that you want this working dynamically. So you can use the ContainerView, like described by the error message:
App.StickiesView = Ember.ContainerView.extend({
click: function() {
var stickie = Ember.View.create({
templateName: 'stickie',
content: 'write your notes here'
});
this.pushObject(stickie);
}
})
I see in your code a lot of views with the click event, ember encourage you to use actions, this give more flexibility, error/loading handling etc. I think is a good idea to use it.
I hope it helps
You should probably read this guide that explains that ContainerView is. Also, I don't think it's necessary to create another View to append a template to another template.

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