# Xây dựng giao diện (ok)

![](https://2726517656-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M1E4Gk2ppVKb4olmnun%2F-MeXWLmEJtyTRIm_kKFD%2F-MeXWiERYk4JUY7X6Weu%2FScreenshot_1.jpg?alt=media\&token=64df182d-6774-42c3-9403-551be2a8da2c)

{% file src="https://2726517656-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M1E4Gk2ppVKb4olmnun%2F-Mguwms6tqy_VDJJNR1v%2F-Mgv88hBO8943xmGHJ2w%2Fbackbonejs.sql?alt=media&token=02ca3005-3668-47e2-950e-b6e48ded6303" %}

{% embed url="https://routers.js" %}

```
"use strict";
window.APP = window.APP || {};
APP.crudRouter = Backbone.Router.extend({
  routes: {
    "crud/new": "create",
    "crud/index": "index",
    "crud/:id/edit": "edit",
    "crud/active": "active",
    "crud/disable": "disable"
  },
  $container: $('#primary-content'),
  initialize: function () {
    this.collection = new APP.crudCollection();
    this.collection.fetch({ajaxSync: false, async: false});
    APP.helpers.debug(this.collection);
    this.index();
    // start backbone watching url changes
    Backbone.history.start();
    var pubnub = PUBNUB.init({
      publish_key: 'demo',
      subscribe_key: 'demo'
    });
  },
  create: function () {
    var view = new APP.crudNewView({
      collection: this.collection,
      model: new APP.crudModel()
    });
    this.$container.html(view.render().el);
  },
  edit: function (id) {
    var view = new APP.crudEditView({model: this.collection.get(id)});
    this.$container.html(view.render().el);
  },

  index: function () {
    var view = new APP.crudIndexView({collection: this.collection});
    this.$container.html(view.render().el);
    $(document).ready(function() {
      $('#list-cruds').DataTable();
    } );
  },
  active: function () {
    var view = new APP.crudIndexView({collection: new APP.crudCollection(this.collection.where({active: "1"}))});
    this.$container.html(view.render().el);
    $(document).ready(function() {
      $('#list-cruds').DataTable();
    } );
  },
  disable: function () {
    var view = new APP.crudIndexView({collection: new APP.crudCollection(this.collection.where({active: "0"}))});
    this.$container.html(view.render().el);
    $(document).ready(function() {
      $('#list-cruds').DataTable();
    } );
  }
});
```

{% embed url="https://models.js" %}

```
"use strict";
APP.crudModel = Backbone.Model.extend({
  url: function() {
    var id = this.get('id');
    return "crud.php?p=item&&id=" + id;
  },
  defaults: {
    name: "",
    address: "",
    email: "",
    phone: "",
    id: "",
    active: 0
  },
  validate: function (attrs) {
    var mailformat = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
    var errors = {};
    if (!attrs.name) {
      errors.name = "name must be required";
    }
    if (!attrs.address) {
      errors.address = "address must be required";
    }
    if (!attrs.email) {
      errors.email = "email must be required";
    } else if (!attrs.email.match(mailformat)) {
      errors.email = "You have entered an invalid email address!" ;
    }
    if (!attrs.phone) {
      errors.phone = "phone must be required";
    } else if(isNaN(attrs.phone)) {
      errors.phone = "phone must be numeric";
    }
    if (!_.isEmpty(errors))
      return errors;
  }
});
APP.crudCollection = Backbone.Collection.extend({
  name: 'crudCollection',
  model: APP.crudModel,
  url: 'crud.php',
});
```

{% embed url="https://index.php" %}

```
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
  <title>CRUD BackboneJS PHP MySQL</title>
  <!-- Bootstrap -->
  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" rel="stylesheet">
  <link href="https://cdn.datatables.net/1.10.16/css/dataTables.bootstrap.min.css" rel="stylesheet">
  <style>
    .alert.fixed {
      position: fixed;
      top: 20px;
      left: 25%;
      width: 50%;
      margin-bottom: 0;
      box-shadow: 0px 0px 10px #454545;
    }
  </style>
  <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
  <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
  <!--[if lt IE 9]>
  <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
  <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="modal fade" id="modalDelete" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        Modal Confirm
      </div>
      <div class="modal-body">
        <div class="content"></div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
        <a href="#" id="delete" class="btn btn-success success">Delete</a>
      </div>
    </div>
  </div>
</div>
<div class="container">

  <div class="page-header">
    <h1>MY CRUD</h1>
  </div>
  <div id="message"></div>
  <div class="panel panel-default">
    <div class="panel-body" id="primary-content">
      <!-- this is content -->
    </div>
  </div>
  <button style="margin:10px 0;" class="btn btn-warning" type="button" data-toggle="collapse" data-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample"><i class="fa fa-desktop"></i> Show Output JSON</button>
  <div class="collapse" id="collapseExample">
    <code id="output" style="display:block;white-space:pre-wrap;"></code>
  </div>
</div>
<script type="text/jst" id="formTemplate">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <div class="alert alert-danger fade in" style="display:none;"></div>
                <form>
                    <h2><%= name %></h2>
                    <div class="form-group">
                        <label>Name:</label>
                        <input type="text" class="form-control" name="name" value="<%= name %>" />
                    </div>
                    <div class="form-group">
                        <label>Email:</label>
                        <input type="text" class="form-control" name="email" value="<%= email %>" />
                    </div>
                    <div class="form-group">
                        <label>Phone:</label>
                        <input type="text" class="form-control" name="phone" value="<%= phone %>" />
                    </div>
                    <div class="form-group">
                        <label>Address:</label>
                        <textarea class="form-control" rows="5" name="address"><%= address %></textarea>
                    </div>
                    <div class="form-group">
                        <label>Active:</label>
                        <% if(_.isEmpty(active) == false && active == 1) { %>
                            <input type="checkbox" name="active" value="1" checked>
                        <% } else { %>
                            <input type="checkbox" name="active" value="0">
                        <% } %>
                    </div>
                    <button class="save btn btn-large btn-info" type="submit">Save</button>
                    <a href="#crud/index" class="btn btn-large btn-default">Cancel</a>
                </form>
            </div>
        </div>
    </script>

<!-- the index container -->
<script type="text/template" id="indexTemplate">

  <a style="margin:10px 0px;" class="btn btn-large btn-info" href="#crud/new"><i class="fa fa-plus"></i> Create New Data</a>

  <div id="collapseExample2">
    <% if (_.isEmpty(cruds)){ %>
    <div class="alert alert-warning">
      <p>There are currently no cruds. Try creating some.</p>
    </div>
    <% } %>

    <table id="list-cruds" class="table table-bordered table-striped">
      <thead>
      <tr>
        <th>No.</th>
        <th>Name</th>
        <th>Email</th>
        <th>Phone</th>
        <th>Address</th>
        <th>Active</th>
        <th width="140">Action</th>
      </tr>
      </thead>
      <tbody>
      <% var idx = 1 %>
      <% _.each(cruds, function (crud) { %>
      <tr>
        <td><%= idx++ %></td>
        <td><%= crud.name %></td>
        <td><%= crud.email %></td>
        <td><%= crud.phone %></td>
        <td><%= crud.address %></td>
        <% if (crud.active == 0) {%>
        <td>Disable</td>
        <% } else { %>
        <td>Active</td>
        <% } %>
        <td class="text-center">
          <a class="btn btn-xs btn-info" href="#crud/<%= crud.id %>/edit"><i class="fa fa-pencil"></i> Edit</a>
          <a id="deleteButton" class="btn btn-xs btn-danger item-destroy" data-id="<%= crud.id %>"><i class="fa fa-trash"></i> Delete</a>
        </td>
      </tr>
      <% }); %>
      </tbody>
    </table>
    <a style="margin:10px 0px;" class="btn btn-large btn-info" href="#crud/index"> All</a>
    <a style="margin:10px 0px;" class="btn btn-large btn-info" href="#crud/active"> Active</a>
    <a style="margin:10px 0px;" class="btn btn-large btn-info" href="#crud/disable"> Disable</a>
  </div>

</script>

<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="assets/js/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/backbone/underscore-min.js"></script>
<script src="assets/backbone/backbone-min.js"></script>
<script src="assets/backbone/backbone.localStorage.js"></script>
<script src="assets/js/pubnub.min.js"></script>
<script src="bower_components/pubnub-backbone/backbone-pubnub.min.js"></script>
<script>
  var pubnub = PUBNUB.init({
    subscribe_key: 'sub-c-4c7f1748-ced1-11e2-a5be-02ee2ddab7fe',
    publish_key: 'pub-c-6dd9f234-e11e-4345-92c4-f723de52df70',
  });
</script>
<script src="routers.js"></script>
<script src="models.js"></script>
<script src="views/view.js"></script>
<script src="helpers.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/dataTables.bootstrap.min.js"></script>
<script>
  var app = new APP.crudRouter();
</script>
</body>
</html>
```

{% embed url="https://helpers.js" %}

```
(function () {
  APP.helpers = {
    debug: function (collection) {
      collection.on('all', function () {
        $('#output').text(JSON.stringify(collection.toJSON(), null, 4));
      });
      collection.trigger('reset');
    },
    showErrors: function (note, errors) {
      $('.help-block').remove();
      _.each(_.keys(errors), function (key) {
        $('*[name=' + key + ']').parent().addClass('has-error');
        $('<span class="help-block has-error">'+ errors[key] +'</span>').insertAfter($('*[name=' + key + ']'));
      });
    }
  };
}());
```

{% embed url="https://crud.php" %}

```
<?php
$db = new PDO('mysql:host=localhost;dbname=backbone_phpmysql', 'root', 'root');
$page = isset($_GET['p'])? $_GET['p'] : '';
if($page=='add'){
  $sql = "INSERT INTO crud values (:id,:nm,:em,:hp,:ad,:at)";
  $query = $db->prepare($sql);
  $query->execute(array(":id"=>null,":nm"=>$_POST['name'],":em"=>$_POST['email'],":hp"=>$_POST['phone'],":ad"=>$_POST['address'],":at"=>$_POST['active']));
} else if($page=='edit'){
  $sql = "UPDATE crud SET name= :nm, email= :em, phone= :hp, address= :ad, active= :at WHERE id = :id";
  $query = $db->prepare($sql);
  $query->execute(array(":id"=>$_POST['id'],":nm"=>$_POST['name'],":em"=>$_POST['email'],":hp"=>$_POST['phone'],":ad"=>$_POST['address'], ":at"=>$_POST['active']));
} else if($page=='trash'){
  $sql = "DELETE FROM crud WHERE id = :id";
  $query = $db->prepare($sql);
  $query->execute(array(":id"=>$_POST['id']));
} else if($page=='item'){
  $statement = $db->query("SELECT * FROM crud WHERE id = ".$_GET['id']);
  $statement->setFetchMode(PDO::FETCH_ASSOC);
  echo json_encode($statement->fetch());
} else{
  $statement = $db->query('SELECT * FROM crud');
  $statement->setFetchMode(PDO::FETCH_ASSOC);
  echo json_encode($statement->fetchAll());
}
?>
```

views/view.js

```
"use strict";
APP.crudIndexView = Backbone.View.extend({
  template: _.template($('#indexTemplate').html()),
  events: {
    'click .item-destroy': 'destroy'
  },
  destroy: function (e) {
    $('#modalDelete .modal-content .modal-body .content').html("are you sure delete ?");
    $('#modalDelete').modal('toggle');
    var id = $(e.currentTarget).attr("data-id");
    var crud = this.collection.get(id);
    $('#delete').click(function(){
      $('#modalDelete').modal('hide');
      if (crud.destroy()) {
        new APP.AlertView.show("CRUD", "Deleted Success", "success");
      } else {
        new APP.AlertView.show("CRUD", "Deleted Error", "danger");
      }
      $.post("crud.php?p=trash", {id: id}, function (data) {
        Backbone.history.navigate("crud/index", {trigger: true});
      });
    });
  },
  render: function () {
    this.$el.html(
      this.template({cruds: this.collection.toJSON()})
    );
    return this;
  }
});
```



