I was working on developing a comment page based on https://thinkster.io/mean-stack-tutorial. But the page does not appear at all. Here is the code:
In index.ejs in views directory:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.js"></script>
<script src="/javascripts/ang.js"></script>
</head>
<body ng-app="peopleComments">
<script type="text/ng-template" id="/home.html">
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="page-header">
<h2>Learn. Share. Popularize.</h2>
</div>
<p>Share here to let the world know.</p>
<hr/>
<div ng-repeat="comment in comments|orderBy:'-upvotes'" style="line-height:25px">
{{comment.username}} - {{comment.contents}}
<br>
{{comment.upvotes}}
<span class="glyphicon glyphicon-triangle-top" ng-click="increaseUpvotes(comment)" style="color:green"></span>
{{comment.downvotes}}
<span class="glyphicon glyphicon-triangle-bottom" ng-click="increaseDownvotes(comment)" style="color:red"></span>
<hr/>
</div>
<form ng-submit="addComment()">
<div class="col-xs-2">
<div class="form-group">
<input type="text" class="form-control" placeholder="Your Name" ng-model="username"></input>
</div>
</div>
<div class="col-xs-8">
<div class="form-group">
<input type="text" class="form-control" placeholder="What would you like to share?" ng-model="contents"></input>
</div>
</div>
<button class="btn btn-info" type="submit">Add My Entry</button>
</form>
</div>
</div>
</div>
</script>
</body>
</html>
In comments.js in models directory:
var mongoose = require('mongoose');
var CommentSchema = new mongoose.Schema({
username: String,
contents: String,
upvotes: {type: Number, default: 0},
downvotes:{type:Number, default:0}
});
CommentSchema.methods.upvote=function(cb){
this.upvotes+=1;
this.save(cb);
};
mongoose.model('Comment', CommentSchema);
In ang.js in public/javascripts directory:
var app=angular.module('peopleComments',['ui.router']);
app.factory('comments',['$http', function($http){
var c={
comments:[]
};
//loading all existing comments with getAll()
c.getAll=function(){
return $http.get('/comments').success(function(data){
angular.copy(data, c.comments);
});
};
//function which creates the new comments for updating in the database
c.create = function(comment) {
return $http.post('/comments', comment).success(function(data){
c.comments.push(data);
});
};
app.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
//setting up a home state
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home.html',
controller: 'Base',
resolve: {
comment: ['comments', function(comments){ //using resolve property of ui-router - not rendering???
return comments.getAll();
}]
}
});
$urlRouterProvider.otherwise('home');
}]);
app.controller('Base',[
'$scope','comments',function($scope,comments){
$scope.addComment=function(){ //add new comments to the server/display existing ones
$scope.comments=comments.comments;
if(!$scope.username||$scope.username=='') {$scope.username='Anonymous';}
if(!$scope.contents||$scope.contents==''){return;}
comments.create({
username: $scope.username,
contents: $scope.contents,
}); $scope.comments.push({username:$scope.username,contents:$scope.contents,upvotes:0,downvotes:0});
$scope.username='';
$scope.contents='';
}
$scope.comments = [
{username: 'Diana', contents:'In either a quantum world or in a higher dimension, the past, present and future co-exist!', upvotes: 5, downvotes:0},
{username: 'Cindy', contents:'Never wash strawberries or any berry unless you intend to eat them right away or they will mold.', upvotes: 7, downvotes:0}
];
}]);
The comments given above should appear.. But they aren't.. Why??
I think your problem is that you've created a template, but you're not using the template.
I'm not 100% sure you need a template but try:
<div ng-include src="home.html"></div>
See this example of switching templates dynamically JSFiddle
It looks like the Controller will not wait for comment to load because it doesn't depend on it. Making the controller depend on the comment promise as well as the comments service should make the dependency clear to Angular.
app.controller('Base',[
'$scope','comments', 'comment', function($scope,comments,_comment){
// ...
}]);
The mistake was that I had to add
<ui-view></ui-view>
where I needed my template to load as per the ui-router syntax.
Related
everyone, I have another question related to Laravel/AngularJS.
In my mini-project, I have form which user can post question in the form, but when I click submit button, there are no requests (from inspect in Google Chrome). However, I have a Log in interface, the button is working very well. I use the same logic, same html structure. And I am wondering how can I fix this problem.
I have been debugging this for 2 hours, have been Googling for a long time. Please help me out!!
Below are the codes.
// Add question page
<script type="text/ng-template" id="question.add.tpl">
<div ng-controller="QuestionAddController" class="question-add container">
<div class="card">
<form name="question_add_form" ng-submit="Question.add()">
<div class="input-group">
<label>Title</label>
<input type="text"
name="title"
ng-minlength="5"
ng-maxlength="255"
ng-model="Question.new_question.title"
required>
</div>
<div class="input-group">
<label>Description</label>
<textarea type="text"
name="desc"
ng-model="Question.new_question.desc">
</textarea>
</div>
<div class="input-group">
<button ng-disabled="question_add_form.$invalid"
class="primary"
type="submit">Submit</button>
</div>
</form>
</div>
</div>
</script>
// Service and Controller
.service('QuestionService', [
'$http',
'$state',
function ($http, $state) {
var me = this;
me.new_question = {};
me.go_add_question = function () {
console.log(1);
$state.go('question.add');
};
me.add = function () {
if (!me.new_question.title)
return;
$http.post('/api/question/add', me.new_question)
.then(function (r) {
console.log('r', r);
// if (r.data.status) {
// console.log(r.data);
// me.new_question = {};
// $state.go('home');
// }
}, function (e) {
console.log('e', e);
})
}
}
])
.controller('QuestionAddController', [
'$scope',
'QuestionService',
function (QuestionService, $scope) {
$scope.Question = QuestionService;
}
])
in QuestionService.add(), there is no "return value" (console.log('r', r);) in my browser.
I make sure routes and url are working fine by directly typing the address in browser. Any suggestion will be highly appreciated!
Thanks in advance!!!
Edit:
Besides, the button Add Question is not working, too. I have to use ui-sref to make it redirect to the target url, will this be the reason why the submit button is not working (like I use ui-sref not the ng-submit to redirect)
// Add question
<div class="navbar clearfix">
<div class="container">
<div class="fl">
<div class="navbar-item brand">somethingHere</div>
<form ng-submit="Question.go_add_question()" id="quick_ask" ng-controller="QuestionAddController">
<div class="navbar-item">
<input ng-model="Question.new_question.title" type="text">
</div>
<div class="navbar-item">
<button ui-sref="question.add" type="submit">Add question</button> <!--ui-sref="question.add"-->
</div>
</form>
</div>
<blablabla something not important here!!!!>
Your injections in the controller is the wrong order. Should be
.controller('QuestionAddController', [
'$scope',
'QuestionService',
function ($scope, QuestionService) {
$scope.Question = QuestionService;
}
])
EDIT:
The ordering itself does not really matter, but the controller function argument ordering must match the ordering in the array. E.g.
Correct:
['QuestionService', 'Service2', '$scope', function(QuestionService, Service2, $scope) { ...
Incorrect:
['QuestionService', 'Service2', '$scope', function(QuestionService, scope, Service2) { ...
The reason to define the controller with array is so that the code can be minified
The page of this app just loads blank. I i searched the problem for hours and still can't find the problem. Angular is 1.3.5 and Angular-route is v1.2.28.
This is index.html:
<html ng-app="myApp">
<head>
<script src="js/angulark.min.js"></script>
<script src="js/angular-routek.js"></script>
<script>
var myApp = angular.module('myApp', ['ngRoute']);
myApp.config(function ($routeProvider) {
$routeProvider
.when('/',
{
controller: 'MainController',
templateUrl: 'views/nameView.html';
})
.when('/cityView',
{
controller: 'MainController',
templateUrl: 'views/cityView.html';
})
.otherwise({ redirectTo: '/' });
});
myApp.controller('MainController', ['$scope', function($scope) {
$scope.customers = [
{ name: 'Andre Queiroz', city: 'Rio de Janeiro' },
{ name: 'Fulano', city: 'Sao Paulo'},
{ name: 'Beltrano', city: 'Curitiba' }
];
$scope.addCustomer() = function () {
$scope.customers.push(
{ name: $scope.newCustomer.name, city: $scope.newCustomer.city }
);
};
}]);
</script>
<title>Meu Aplicativo</title>
</head>
<body>
<div>
<!-- Placeholder for views -->
<div ng-view> </div>
</div>
</body>
</html>
This is nameView.html
<div class="container">
<div ng-controller="MainController">
<div>
<h2>View 1</h2>
Name: <input type="text" ng-model="filter.name"/>
</div>
<br />
<ul>
<li ng-repeat="cust in customers | filter:filter.name | orderBy:'city'">{{cust.name | uppercase}} - {{cust.city}}</li>
</ul>
</div
<div>
<p>Customer name:</p>
<input type="text" ng-model="newCustomer.name" />
<p>Customer city:</p>
<input type="text" ng-model="newCustomer.city" />
<button ng-click="addCustomer()">Add customer </button>
View 2
</div>
</div>
</div>
The cityView.html is the same but with no addCustomer stuff. I was dividing into module file and so on, but i put it in one file to see if it worked.
There is a mistake in index.html javascript.
Inside MainController change your code
$scope.addCustomer() = function () {
$scope.customers.push(
{ name: $scope.newCustomer.name, city: $scope.newCustomer.city }
);
};
to
$scope.addCustomer= function () {
$scope.customers.push(
{ name: $scope.newCustomer.name, city: $scope.newCustomer.city }
);
};
it should $scope.addCustomer= instead of $scope.addCustomer()=
You're actually doing well. Most of erros are syntax.
Error 1: Remove ; from templateUrl inside $routeProvider.when()
Eq. templateUrl: 'views/cityView.html'
Error 2: Can't have parentheses to create a method with this sintaxe
$scope: Eq. $scope.newfunction = function() {...}
<html ng-app="myApp">
<head>
<script src="js/angulark.min.js"></script>
<script src="js/angular-routek.js"></script>
<script>
var myApp = angular.module('myApp', ['ngRoute']);
myApp.config(function ($routeProvider) {
$routeProvider
.when('/',
{
controller: 'MainController',
templateUrl: 'views/nameView.html'
})
.when('/cityView',
{
controller: 'MainController',
templateUrl: 'views/cityView.html'
})
.otherwise({ redirectTo: '/' });
});
myApp.controller('MainController', ['$scope', function($scope) {
$scope.customers = [
{ name: 'Andre Queiroz', city: 'Rio de Janeiro' },
{ name: 'Fulano', city: 'Sao Paulo'},
{ name: 'Beltrano', city: 'Curitiba' }
];
$scope.addCustomer = function () {
$scope.customers.push(
{ name: $scope.newCustomer.name, city: $scope.newCustomer.city }
);
};
}]);
</script>
<title>Meu Aplicativo</title>
</head>
<body>
<div>
<!-- Placeholder for views -->
<div ng-view> </div>
</div>
</body>
</html>
There're some HTML errors in your view. Make sure to validate your HTML.
Error: In the line 11, you must fix from </div to </div>
Also, you don't need to add a controller. You already added on your config:
Remove it from your view: From <div
ng-controller="MainController"> to <div>
Not required, but best practice
On your last line, there's a spare </div>, get rid of it:
<div class="container">
<div ng-controller="MainController">
<div>
<h2>View 1</h2>
Name: <input type="text" ng-model="filter.name"/>
</div>
<br />
<ul>
<li ng-repeat="cust in customers | filter:filter.name | orderBy:'city'">{{cust.name | uppercase}} - {{cust.city}}</li>
</ul>
</div>
<div>
<p>Customer name:</p>
<input type="text" ng-model="newCustomer.name" />
<p>Customer city:</p>
<input type="text" ng-model="newCustomer.city" />
<button ng-click="addCustomer()">Add customer </button>
View 2
</div>
</div>
PS: Make sure you check your syntax errors. Using jshint, jslint or even Chrome dev tools / Firebug will help with that. You can set your editor(Sublimelinter for Sublime for example) to use jshint. Or use a IDE like Webstorm which comes with.
I'm trying to make my first AngularJS application and I've run into a problem.
I have an input:
<input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
A button:
<button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
and an expression:
{{ activeUser }}
I want the text to change to whatever was typed in the input once the button is clicked. For that I have the following controller:
app.controller('View1Ctrl', ['$scope', function($scope) {
$scope.userNameLogin = "";
$scope.activeUser = "Test";
$scope.setActiveUser = function() {
$scope.activeUser = $scope.userNameLogin;
console.log($scope.activeUser);
};
}]);
The initial value "Test" is shown just fine and according to the console the value of "activeUser" is being changed correctly as well. But the text in the view stays the same.
I have seen similar questions where a $scope.$apply() was the answer, but if I add that after the console.log I get
"Error: [$rootScope:inprog] $apply already in progress".
What am I missing here?
EDIT:
I have noticed that If I put the input, button and expression in the same HTML file it all works fine. However my Input and button are in a navbar in index.html while the expression is in view1.html
This is the body of index.html:
<body ng-app="myApp.view1">
<nav class="navbar navbar-inverse navbar-fixed-top" ng-controller="View1Ctrl as view">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="#/view1">Kwetter</a>
</div>
<div class="navbar-collapse collapse" >
<ul class="nav navbar-nav">
<li>Home</li>
<li>Profile</li>
</ul>
<form class="navbar-form navbar-right">
<div class="form-group">
<input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
</div>
<div class="form-group">
<input type="password" placeholder="password" class="form-control">
</div>
<button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
</form>
</div>
</div>
</nav>
<div id="pagewrapper" class="container">
<div ng-view></div>
<div>Angular seed app: v<span app-version></span></div>
</div>
and this is my view1.html
<div ng-controller="View1Ctrl as view">
<!-- row 1: welcome -->
<div class="row">
<div class="col-md-12 pull-left">
<image ng-src="{{ view.users[0].avatar }}"/>
<!-- If I put the button and input here it will work -->
<input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
<button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
{{ activeUser }}
</div>
</div>
<!-- row 2: main content -->
<!-- left the rest of the content out because it would just clutter the page -->
I tried placing the ng-controller in <div id="pagewrapper" class="container"> instead of the first div of view1.html, but that made no difference.
I think u have misplaced the button or textbox or expression,
note : these should be inside the ng-controller.
please try this, it will work
<html>
<head>
<script data-require="angular.js#*" data-semver="1.4.0-beta.6" src="https://code.angularjs.org/1.4.0-beta.6/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="app">
<div ng-controller="View1Ctrl">
<input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
<button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
{{activeUser}}
</div>
<h1>Hello Plunker!</h1>
</body>
</html>
script.js code
var app = angular.module("app",[]);
app.controller('View1Ctrl', ['$scope', function($scope) {
$scope.userNameLogin = "";
$scope.activeUser = "Test";
$scope.setActiveUser = function() {
$scope.activeUser = $scope.userNameLogin;
console.log($scope.activeUser);
};
}]);
refer http://plnkr.co/edit/ixbByBQ9nGm4XEqEFi4t?p=preview
You have the properties directly on $scope and that is breaking the binding. Instead try:
app.controller('View1Ctrl', ['$scope', function($scope) {
$scope.userInfo = {
userNameLogin: "",
activeUser:"Test"
}
$scope.setActiveUser = function() {
$scope.uesrInfo.activeUser = $scope.userInfo.userNameLogin;
console.log($scope.activeUser);
};
}]);
and in your view:
{{userInfo.activeUser}}
From Egghead.io https://egghead.io/lessons/angularjs-the-dot
Within your code I can't see anything causing the problem. I made a fiddle, that shows that your code works:
http://jsfiddle.net/xxvsn8xs/
You need to declare the ng-appand the ng-controller of course, like in the fiddle, to let the app work at all.
Also, an view update might not occur, if setting the activeUser actually occurs outside of the angular scope, which might be within an external library or whatever. It is true, that these could be achieved by calling $scope.$apply() directly, but it is nor recommended, as the digest might already be in progress. This is the case in your code, as why you get the according error message.
Instead use angulars $timeout service with a callback and 0 delay, that applies the value to $scope.activeUser. $timeout will check, if a digest cycle is in progress and if not, will start one.
$scope.setActiveUser = function() {
$timeout(function () {
$scope.activeUser = $scope.userNameLogin;
console.log($scope.activeUser);
});
};
Don't forget to define $timeout in your controllers dependencies:
app.controller('View1Ctrl', ['$scope', '$timeout', function($scope, $timeout) {
Angular watches the variable you bind to $scope, but if you replace that variable Angular is not able to detect it. That's why $apply would be a suggestion.
Another suggestion is to bind the variable to a 'model' variable:
app.controller('View1Ctrl', ['$scope', function($scope) {
$scope.userNameLogin = "";
$scope.myData = { activeUser: "Test" };
$scope.setActiveUser = function() {
// Angular will pick up the change in the myData object, and will update all variables attached to it
$scope.myData.activeUser = $scope.userNameLogin;
console.log($scope.myData.activeUser);
};
}]);
view:
{{ myData.activeUser }}
Do you execute your application in Apache ? I'd the same issue when I was using file:// And I fixed my issue by using a localhost.
I put my navbar (containing the input and button) in a partial and made a new directive for it. Instead of placing the navbar in the index.html I put it in the individual partials and now it works fine. I suspect the problem had something to do with different scopes.
navbar html:
<a class="navbar-brand" href="#/view1">
Kwetter
<image id="navbar-image" src="src/kwetter_logo.png"/>
</a>
</div>
<div class="navbar-collapse collapse" >
<ul class="nav navbar-nav">
<li>Home</li>
<li>Profile</li>
</ul>
<form class="navbar-form navbar-right">
<div class="form-group">
<input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
</div>
<div class="form-group">
<input type="password" placeholder="password" class="form-control">
</div>
<button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
</form>
</div>
</div>
the directive:
app.directive('navbar', function() {
return {
restrict: 'E',
templateUrl: 'partials/navbar.html',
controller: 'View1Ctrl as view'
}
});
Then I just added <navbar></navbar> to every view where I want a navbar.
Thanks everyone, your help pushed me in the right direction.
I'm trying to get books to display based on the assignment above but can't figure out what is wrong for the life of me.
I built the service and modified the controller and view pages to the point where I believe they should display the books in the view, but I'm just seeing a blank page.
I feel like I am probably not retrieving the data properly and accessing it in the view/html.
Any ideas? Link to jsFiddle.
Index.html
<body ng-app="ReaderApp">
<div class="header">
<div class="container">
Reader
</div>
</div>
<div class="main">
<div class="container">
<div ng-view></div>
</div>
</div>
<!-- Modules -->
<script src="js/app.js"></script>
<!-- Controllers -->
<script src="js/controllers/BookshelfController.js"></script>
<script src="js/controllers/BookController.js"></script>
<script src="js/controllers/ChapterController.js"></script>
<!-- Services -->
<script src="js/services/books.js"></script>
</body>
js/apps.js
var app = angular.module('ReaderApp', ['ngRoute']);
app.config(function($routeProvider){
$routeProvider
.when('/books', {
controller: 'BookshelfController',
templateUrl: 'views/bookshelf.html'
})
.otherwise({
redirecTo: '/books'
});
});
js/services/books.js
app.factory('books', ['$http', function($http) {
return $http.get('https://s3.amazonaws.com/codecademy-content/courses/ltp4/books-api/books.json')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}]);
js/controllers/BookshelfController
app.controller('BookshelfController', ['$scope', 'books', function($scope, books) {
books.success(function(data) {
$scope.myBooks = data;
});
}]);
js/views/bookshelf.html
<div class="bookshelf row">
<!--
TODO: Loop through myBooks and display each one with this HTML
<div class="book col-md-3">
<a href="#/books/{{$index}}">
TODO: Add the book's cover here
<h3 class="title"> </h3>
<p class="author"> </p>
</a>
</div>
-->
<div class="book col-md-3" ng-repeat="book in myBooks">
<a href="#/books/{{$index}}">
<img ng-src="{{ book.cover }}">
<h3 class="title">{{ book.title }}</h3>
<p class="author">by {{ book.author }}</p>
</a>
</div>
</div>
I think I had the same trouble and my problem was in the router. Try adding array brackets ( [ ] ) and the '$routeProvider' string in your config method (app.js) like this:
app.config(['$routeProvider', function($routeProvider) {
// Normal router stuff goes here
}]);
Coming from Ember, the syntax is a little weird so I've been using this tutorial as reference when I get stuck.
Does anyone happen to know How to show data from server, right now ive been showing related models in basic handlebars like this
{{
view Ember.Select
prompt="Organization"
contentBinding="organizations"
optionValuePath="content.id"
optionLabelPath="content.name"
selectionBinding="selectedOrganization"
}}
But i need to create an has many form... which im duplicating using views? Is using views even the right path to go ?!
{{#each view.anotherField}}
{{view Ember.TextField value=view.name}}
{{/each}}
Here is the output of my form, u can see Organizatons form being doubled
JSbin http://jsbin.com/efeReDer/7/edit
Today I came up with this... :D Kinda serves the purpose ? looks ugly tho
http://emberjs.jsbin.com/acUCocu/6/edit
Basically i made an empty model which i then each loop.
On action i "store.create".empty record to it.
Give me your thoughts on this :)
Also is there a way to make these fields indepedent ? without all changing their content while an input is changed.
Cheers,
kristjan
Here you can find an example to work on, of what i think you are asking
http://emberjs.jsbin.com/iPeHuNA/1/edit
js
Tried to separate the entities related to the model of the app, from how they will be displayed.Created an ember class App.Person that will hold the data from server. I have not used ember-data, but it is quite easy to replace the classes with ember-data notation and the dummy ajax calls with respective store calls etc, if desired.
App = Ember.Application.create();
App.Router.map(function() {
this.route("persons");
});
App.IndexRoute = Ember.Route.extend({
beforeModel: function() {
this.transitionTo("persons");
}
});
App.PersonsRoute = Ember.Route.extend({
model:function(){
return $.ajax({url:"/"}).then(function(){/*in url it is required to place the actual server address that will return data e.g. from a rest web service*/
/*let's imagine that the following data has been returned from the server*/
/*i.e. two Person entities have already been stored to the server and now are retrieved to display*/
var personsData = [];
var person1 = App.Person.create({id:1,fname:"Person1",lname:"First",genderId:2});
var person2 = App.Person.create({id:2,fname:"Person2",lname:"Second",genderId:1});
personsData.pushObject(person1);
personsData.pushObject(person2);
return personsData;
});
},
setupController:function(controller,model){
/*this could also be retrieved from server*/
/*let's mimic a call*/
$.ajax({url:"/",success:function(){
/*This will run async but ember's binding will preper everything.If this is not acceptable, then initialization of lists' values/dictionary values can take place in any earlier phase of the app. */
var gendersData = [];
gendersData.pushObject(App.Gender.create({id:1,type:"male"}));
gendersData.pushObject(App.Gender.create({id:2,type:"female"}));
controller.set("genders",gendersData);
model.forEach(function(person){
person.set("gender",gendersData.findBy("id",person.get("genderId")));
});
}});
controller.set("model",model);
}
});
App.PersonsController = Ember.ArrayController.extend({
genders:[],
actions:{
addPerson:function(){
this.get("model").pushObject(App.Person.create({id:Date.now(),fname:"",lname:""}));
},
print:function(){
console.log(this.get("model"));
}
}
});
App.PersonFormView = Ember.View.extend({
templateName:"personForm",
/*layoutName:"simple-row"*/
layoutName:"collapsible-row"
});
App.Person = Ember.Object.extend({
id:null,
fname:"",
lname:"",
gender:null
});
App.Gender = Ember.Object.extend({
id:null,
type:null
});
html/hbs
created a view that takes care of how each App.Person instance gets rendered. As example partial and layouts have been used to accomodate bootstrap styling, as i noticed you used some in your example.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/normalize/2.1.0/normalize.css">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
</head>
<body>
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="persons">
{{#each person in this}}
{{view App.PersonFormView}}
{{/each}}
<br/><br/>
{{partial "buttons"}}
</script>
<script type="text/x-handlebars" data-template-name="_buttons">
<button type="button" class="btn btn-primary" {{action "addPerson"}}>
add
</button>
<button type="button" class="btn btn-primary" {{action "print"}}>
print results to console
</button>
</script>
<script type="text/x-handlebars" data-template-name="personForm">
<div class="row">
<div class="col-md-6 col-xs-5">
<div class="form-group">
<label>First Name</label>
{{input class="form-control" placeholder="First Name" value=person.fname}}
</div>
</div>
<div class="col-md-6 col-xs-5">
<div class="form-group">
<label>Last Name</label>
{{input class="form-control" placeholder="Last Name" value=person.lname}}
</div>
</div>
</div>
<div class="row">
<div class="col-md-2 col-xs-4">
{{
view Ember.Select
prompt="Gender"
content=controller.genders
optionValuePath="content.id"
optionLabelPath="content.type"
selectionBinding=person.gender
class="form-control"
}}
</div>
</div>
<!--</div>-->
</script>
<script type="text/x-handlebars" data-template-name="simple-row">
<div class="row">
{{yield}}
</div>
<br/><br/>
</script>
<script type="text/x-handlebars" data-template-name="collapsible-row">
<div class="panel-group" >
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" href=#{{unbound person.id}}>
person:{{person.fname}}
</a>
</h4>
</div>
<div id={{unbound person.id}} class="panel-collapse collapse">
<div class="panel-body">
{{yield}}
</div>
</div>
</div>
</div>
</br>
</script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.1.2.js"></script>
<script src="http://builds.emberjs.com/tags/v1.2.0/ember.min.js"></script>
</body>
</html>