I've been working on a Angular.js tutorial that I now want to extend. It's a simple CRUD app that has a list of templates: list.html (just records in a db with a title and content), a create form: new.html, and an edit form: edit.html.
Just now list.html loads an array of templates from my REST app and displays them in a table. There is a search form and some sorting functionality.
New.html has a form for creating new templates.
These two .html files are loaded by going to different routes. #/
and #/new
What I want to do now is have one file index.html which loads both list.html inside one div and then new.html inside another div. The idea is that the list of records will always be displayed on the left and then the other partials will be loaded into the area to the right. So clicking on a template in the list will open it in the area next to the list but the list remains untouched. Then if i click the new template button the new template form will re-appear in the content area but the list will remain untouched.
Here is my code:
app.js
var MailStash = angular.module("MailStash", ["ngResource"]).
config(function($routeProvider){
$routeProvider.
when('/', {controller: ListCtrl, templateUrl: '/js/partials/list.html'}).
when('/new', {controller: CreateCtrl, templateUrl: '/js/partials/new.html'}).
when('/edit/:editId', {controller: EditCtrl, templateUrl: '/js/partials/edit.html'})
});
MailStash.factory('Template', function($resource){
return $resource('/api/v1/template/:id', {id: '@id'}, { update: { method: 'PUT' } });
});
var EditCtrl = function($scope, $location, $routeParams, Template) {
$scope.action = "Update";
var id = $routeParams.editId;
$scope.template = Template.get({id: id});
$scope.save = function () {
Template.update({id: id}, $scope.template, function () {
$location.path('/');
});
};
}
var CreateCtrl = function($scope, $location, Template) {
$scope.save = function() {
Template.save($scope.template, function(){
$location.path('/');
});
}
}
var ListCtrl = function($scope, $location, Template) {
$scope.search = function() {
Template.query({
q: $scope.query,
sort_order: $scope.sort_order,
is_desc: $scope.is_desc,
offset: $scope.offset,
limit: $scope.limit
},
function(data){
$scope.more = data.length === 20;
$scope.templates = $scope.templates.concat(data);
});
}
$scope.sort = function(col) {
if($scope.sort_order === col) {
$scope.is_desc = !$scope.is_desc;
} else {
$scope.sort_order = col;
$scope.is_desc = false;
}
$scope.reset();
};
$scope.showMore = function(){
$scope.offset += $scope.limit;
$scope.search();
};
$scope.hasMore = function(){
return $scope.more;
}
$scope.reset = function() {
$scope.limit = 10;
$scope.offset = 0;
$scope.templates = [];
$scope.more = true;
$scope.search();
}
$scope.delete = function() {
var id = this.template.id;
Template.delete({id: id}, function(){
$('#template_'+id).fadeOut();
});
}
$scope.sort_order = "title";
$scope.is_desc = false;
$scope.reset();
};
List.html:
<form class="form-search">
<div class="input-append">
<input type="text" ng-model="query" class="input-medium search-query" placeholder="Search">
<button ng-click="reset()" type="submit" class="btn"><i class="icon-search"></i></button>
</div>
<button ng-click="query=''; reset()" ng-disabled="!query" type="submit" class="btn">Reset</button>
</form>
<p class="sort">
Sort:
<a ng-click="sort('title')">Title</a>
<span ng-show="sort_order=='title' && is_desc==true"><i class="icon icon-arrow-down"> </i></span>
<span ng-show="sort_order=='title' && is_desc==false"><i class="icon icon-arrow-up"> </i></span>
|
<a ng-click="sort('created_at')">Date Created</a>
<span ng-show="sort_order=='created_at' && is_desc==true"><i class="icon icon-arrow-down"> </i></span>
<span ng-show="sort_order=='created_at' && is_desc==false"><i class="icon icon-arrow-up"> </i></span>
</p>
<table class="table">
<tbody>
<tr ng-repeat="template in templates" id="template_{{template.id}}">
<td>{{template.title}}</td>
</tr>
</tbody>
</table>
<a ng-show="hasMore()" ng-click="showMore()">Show more</a>
<hr>
<a href="/#/new" class="btn"><i class="icon icon-plus"> </i> New Template</a>
New.html
<h2>New Template</h2>
<form name="new_template">
<div class="control-group" ng-class="{error: form.title.$invalid}">
<div class="controls">
<input type="text" class="span6" ng-model="template.title" name="title" id="title" value="" placeholder="Template name" />
</div>
</div>
<div class="control-group" ng-class="{errors: form.content.$invalid}">
<div class="controls">
<textarea name="content" ng-model="template.content" id="content" class="template-content span12" rows="15"></textarea>
</div>
</div>
<div class="form-actions">
<button ng-click="save()" class="btn btn-primary save-template">Save Template</button>
</div>
</form>
My layout file:
<!DOCTYPE html>
<html ng-app="MailStash" xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://ogp.me/ns/fb#">
<head>
<title>MailStash</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="Billy Jones - http://theninthnode.com">
{{ Html::style('css/bootstrap.cerulean.min.css') }}
@yield('css')
{{ Html::style('css/style.css') }}
</head>
<body class="preview" data-spy="scroll" data-target=".subnav" data-offset="80">
<div class="container-fluid">
@include('common.header-fluid')
</div>
<div class="container-fluid main">
<div ng-view></div>
@include('common.footer')
</div>
{{ HTML::script('js/jquery.min.js') }}
{{ HTML::script('js/bootstrap.min.js') }}
{{ HTML::script('js/angular.min.js') }}
{{ HTML::script('js/angular-resource.min.js') }}
{{ HTML::script('js/jquery.dataTables.min.js') }}
@yield('scripts')
{{ HTML::script('js/app.js') }}
{{ HTML::script('js/main.js') }}
</body>
</html>
I tried to use:
<div class="row-fluid">
<div class="span3">
<div ng-include="'/js/partials/list.html'"></div>
</div>
<div class="span9">
<div ng-include="'/js/partials/new.html'"></div>
</div>
</div>
But i lost the functionality of these partials. ie the search form stopped working and the new template form stopped working.
I think what you are saying is you are replacing the <div ng-view></div>
with the last block with 2 ng-include
.
If so you probably don't need the controller
defined in the routing config and need to add ng-controller
attributes to the html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With