AngularJS

De Banane Atomic
Révision datée du 10 octobre 2017 à 22:03 par Nicolas (discussion | contributions) (→‎Routing)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à la navigationAller à la recherche

Liens

Controller

Scripts/app-persons.js
(function () {

    "use strict";

    // création du module
    angular.module("app-persons", []);

})();
Scripts/personsController.js
(function () {

    "use strict";

    // récupération du module et ajout du controller
    angular.module("app-persons")
        .controller("personsController", personsController);

    function personsController() {
        var vm = this;

        this.persons = [
            { Name: "John" },
            { Name: "Mike" }
        ];
    }
})();
Views/Home/Index.cshtml
<div ng-app="app-persons">
    <div ng-controller="personsController as vm">

        <table class="table table-striped">
            <tr ng-repeat="person in vm.persons">
                <td>{{ person.Name }}</td>
            </tr>
        </table>

    </div>
</div>

GET data

Scripts/personsController.js
function personsController($http) {
    var vm = this;
    this.persons = [];
    vm.errorMessage = "";
    vm.isBusy = true;

    $http.get("/api/persons")
        .then(function (response) {
            // success
            angular.copy(response.data, vm.persons);
        }, function (error) {
            // failure
            vm.errorMessage = "Failed to load data: " + error;
        })
        .finally(function () {
            vm.isBusy = false;
        });
}
Views/Home/Index.cshtml
<div class="text-danger" ng-show="vm.errorMessage">{{ vm.errorMessage }}</div>
<div ng-show="vm.isBusy" class="text-center">
    <i class="fa fa-spinner fa-spin"></i>Loading ...
</div>
<table class="table table-striped">
    <tr ng-repeat="person in vm.persons">
        <td>{{ person.Name }}</td>
    </tr>
</table>

POST: add data

Views/Home/Index.cshtml
<!-- ng-submit: liaison avec la fonction javascript lors du submit-->
<form novalidate name="newPersonForm" ng-submit="vm.addPerson()">
    <div class="form-group">
        <label for="name">Name</label>
        <!-- ng-model: binding avec le vm -->
        <!-- required et ng-minlength="3": conditions de validation -->
        <input class="form-control" type="text" id="name" name="name"
               ng-model="vm.newPerson.Name" required ng-minlength="3" />
        <!-- messages d'erreur -->
        <!-- ng-show: condition d'affichage (idForm.inputName.$error.condition) -->
        <span ng-show="newPersonForm.name.$error.required" class="text-warning">Name is required.</span>
        <span ng-show="newPersonForm.name.$error.minlength" class="text-warning">Name must be at least 3 characters.</span>
    </div>
    <div class="form-group">
        <!-- ng-disabled: désactive le bouton si le formulaire n'est pas valide -->
        <input type="submit" value="Add" class="btn btn-success btn-sm"
               ng-disabled="newPersonForm.$invalid"/>
    </div>
</form>
Scripts/personsController.js
// création d'une propriété contenant un objet vide
vm.newPerson = {};
// fonction permettant l'ajout
vm.addPerson = function () {
    vm.isBusy = true;
    vm.errorMessage = "";

    $http.post("/api/persons", vm.newPerson)
        // on suppose que la méthode post retourne le nouvel objet Person en cas de succès
        .then(function (response) {
            // success
            vm.persons.push(response.data);
            // vide les champs du formulaire
            vm.newPerson = {};
        }, function () {
            // failure
            vm.errorMessage = "Failed to add new person.";
        })
        .finally(function () {
            vm.isBusy = false;
        });
};

DELETE data

Views/Home/Index.cshtml
<table class="table table-striped">
    <tr ng-repeat="person in vm.persons">
        <td>{{ person.Name }}</td>
        <td>
            <button class="btn btn-sm btn-primary" ng-click="vm.deletePerson(person)">
                <i class="fa fa-trash"></i>
            </button>
Scripts/personsController.js
vm.deletePerson = function (person) {
    vm.isBusy = true;
    vm.errorMessage = "";

    var i = this.persons.indexOf(person);

    $http.delete("/api/persons/" + i)
        .then(function () {
            // success
            vm.persons.splice(i, 1);
        }, function () {
            // failure
            vm.errorMessage = "Failed to delete person.";
        })
        .finally(function () {
            vm.isBusy = false;
        });
};

Directive

Réutilisation de code.

Scripts/app-person.js
// création du module et liste des dépendances
angular.module("app-persons", ["simpleControls"]);
Scripts/simpleControls.js
(function () {
    "use strict";

    angular.module("simpleControls", [])
        .directive("waitCursor", waitCursor);

    function waitCursor() {
        return {
            // map displayWhen → show
            scope: {
                show: "=displayWhen"
            },
            restrict: "E",
            templateUrl: "/Content/waitCursor.html";
        };
    }
})();
Content/waitCursor.html
<div ng-show="show">
    <div class="text-center">
        <i class="fa fa-spinner fa-spin"></i>Loading ...
    </div>
</div>
Views/Home/Index.cshtml
<!-- passage de vm.isBusy dans le paramètre display-when -->
<wait-cursor display-when="vm.isBusy"></wait-cursor>
<!-- remplace -->
<div ng-show="vm.isBusy" class="text-center">
    <i class="fa fa-spinner fa-spin">Loading ...</i>
</div>

Routing

Installer Nuget → AngularJS.Route

App_Start/BundleConfig.cs
bundles.Add(new ScriptBundle("~/bundles/angular").Include(
            "~/Scripts/angular.js",
            "~/Scripts/angular-route.js",
            "~/Scripts/app-persons.js",
            "~/Scripts/personsController.js"));
Scripts/app-persons.js
angular.module("app-persons", ["ngRoute"])
    .config(function ($routeProvider) {

        $routeProvider.when("/", {
            controller: "personsController",
            controllerAs: "vm",
            templateUrl: "/Content/Templates/personsView.html"
        });

        $routeProvider.otherwise({ redirectTo: "/" });
    });
Views/Home/Index.cshtml
<div ng-app="app-persons">
    <div ng-view></div>
</div>
Content/Templates/personsView.html
<div>
    <table class="table table-striped">
        <tr ng-repeat="person in vm.persons">
            <td>{{ person.Name }}</td>

PUT: update data

Scripts/app-persons.js
$routeProvider.when("/edit:personId", {
    controller: "editPersonController",
    controllerAs: "vm",
    templateUrl: "/Content/Templates/editPersonView.html"
});
Content/Templates/editPersonView.html
<div>
    <a href="#!/" class="btn btn-sm btn-default"><i class="fa fa-angle-left"></i> Back</a>

    <form novalidate name="editPersonForm" ng-submit="vm.editPerson()">
        <div class="form-group">
            <label for="name">Name</label>
            <input class="form-control" type="text" id="name" name="name"
                   ng-model="vm.editedPerson.Name" required ng-minlength="3" />
            <span ng-show="editPersonForm.name.$error.required" class="text-warning">Name is required.</span>
            <span ng-show="editPersonForm.name.$error.minlength" class="text-warning">Name must be at least 3 characters.</span>
        </div>
        <div class="form-group">
            <a href="#!/" class="btn btn-sm btn-default">Cancel</a>
            <input type="submit" value="Ok" class="btn btn-success btn-sm"
                   ng-disabled="editPersonForm.$invalid" />
        </div>
    </form>
</div>
Scripts/editPersonController.js
angular.module("app-persons")
    .controller("editPersonController", editPersonController);

function editPersonController($routeParams, $http) {
    var vm = this;
    vm.errorMessage = "";
    vm.isBusy = true;
    vm.editedPerson = {};

    vm.personId = $routeParams.personId;

    $http.get("/api/persons/" + vm.personId)
        .then(function (response) {
            angular.copy(response.data, vm.editedPerson);
        }, function (error) {
            vm.errorMessage = "Failed to load data: " + error;
        })
        .finally(function () {
            vm.isBusy = false;
        });

    vm.editPerson = function () {
        vm.isBusy = true;
        vm.errorMessage = "";

        $http.put("/api/persons/" + vm.personId, vm.editedPerson)
            .then(function () {
                // avec le binding le nom de la personne a déjà été modifié
                location = '#!/';
            }, function () {
                vm.errorMessage = "Failed to edit person.";
            })
            .finally(function () {
                vm.isBusy = false;
            });
    };
}
Content/Templates/personsView.html
<div>
    <table class="table table-striped">
        <tr ng-repeat="person in vm.persons">
            <td>{{ person.Name }}</td>
            <td>
                <a ng-href="#!/edit/{{ $index }}" class="btn btn-sm btn-primary">
                    <i class="fa fa-edit"></i>
                </a>

Installation

NuGet → AngularJS.Core (v1.6.5)

App_Start/BundleConfig.cs
public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/angular").Include("~/Scripts/angular.js"));
Views/Home/Index.cshtml
@section scripts {
    @Scripts.Render("~/bundles/angular")
}

<div ng-app>
    <div>{{ "2 + 2 = " + (2 + 2) }}</div>
</div>