7

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>
    &nbsp;|&nbsp;
    <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.

1 Answer 1

3

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

Sign up to request clarification or add additional context in comments.

3 Comments

No ng-view has been kept the same. I load index.html into the ng-view by specifying the template in the route. And then inside that I've tried using ng-include to load in two separate template files. I'm wondering 1. how I can have the 2 templates working independently. 2. How to avoid messing up my existing code
did you try setting ng-controller in each of the ng-include instead of in route config?
I added the controller to the ng-include and some of the functionality is back. The problem now is when doing GET or POST all my parameters are being sent as undefined

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.