AngularJS-Tutorial-Serie: Teil 1 – Erstellen eines Kalenders mit WENIGER CSS, Font Awesome und Moment

Dieses AngularJS-Mini-Tutorial für Fortgeschrittene ist Teil 1 einer 5-teiligen Serie, in der Sie jeweils lernen, wie Sie etwas erstellen, das Sie auf Ihrer Webseite verwenden können. In diesem Tutorial erfahren Sie, wie Sie unter anderem mit AngularJS-Direktiven einen Kalender erstellen.

Andere Beiträge in der Serie:


Heute werde ich darüber sprechen, wie man ein Kalendersteuerelement mit erstellt Winkel JS, WENIGER CSS, Schriftart genial und Moment. Ich gehe davon aus, dass Sie mit diesen Tools zumindest halbwegs vertraut sind, aber wenn Sie es nicht sind, schlage ich vor, dass Sie einen Blick auf die obigen Links werfen.

Der Kalender selbst wird eine Angular JS-Anweisung sein, die es dem Benutzer ermöglicht, ein Datum auszuwählen, das auf der Eigenschaft eines Controllers festgelegt wird. Ich habe den Kalender gestylt und werde diesen Stil in dieses Tutorial aufnehmen, aber Sie können das Aussehen natürlich nach Herzenslust anpassen. Wenn Sie die Art von Leser sind, die es vorzieht, ein fertiges Produkt anzusehen und einfach die Quelle selbst zu überprüfen, habe ich eine Demoseite zusammengestellt, die den Kalender zeigt. Du kannst es sehen hier.

Ich werde das Schreiben in ein paar verschiedene Abschnitte unterteilen. Zuerst das HTML. Es ist ziemlich einfach, da es nur die HTML-Kalenderdirektive ist. Dann gehen wir durch den JavaScript-Code, der zeigt, wie ich Angular JS verwende, um den Status der Direktive zu aktualisieren, was wiederum die Kalenderansicht aktualisiert. Abschließend beschreibe ich, was ich mit den einzelnen CSS-Regeln mache, die den Kalender formatieren. Während die meisten CSS einfach sind, gibt es einige Dinge, die ich besprechen werde, die für den Leser neu sein könnten.

Notiz: Das hier gezeigte CSS stimmt möglicherweise nicht genau mit dem überein, was Sie auf der Demoseite sehen, da ich möchte, dass die Demo mit einem hübschen Styling zumindest halbwegs anständig aussieht. Größtenteils werde ich jedoch versuchen, das CSS im Tutorial so einfach wie möglich zu halten.

HTML

Direktive Verwendung

<calendar selected="day"></calendar>

In diesem Fall wäre die Variable auf dem Controller, die mit dem ausgewählten Datum aktualisiert wird, „Tag“.

Kalendervorlage

Da die Kalendervorlage ziemlich groß ist, habe ich sie extrahiert und in einer eigenen HTML-Datei platziert, was die beste Vorgehensweise ist.

<div class="header">
    <i class="fa fa-angle-left" ng-click="previous()"></i>
    <span>{{month.format("MMMM, YYYY")}}</span>
    <i class="fa fa-angle-right" ng-click="next()"></i>
</div>
<div class="week names">
    <span class="day">Sun</span>
    <span class="day">Mon</span>
    <span class="day">Tue</span>
    <span class="day">Wed</span>
    <span class="day">Thu</span>
    <span class="day">Fri</span>
    <span class="day">Sat</span>
</div>
<div class="week" ng-repeat="week in weeks">
    <span class="day" ng-class="{ today: day.isToday, 'different-month': !day.isCurrentMonth, selected: day.date.isSame(selected) }" ng-click="select(day)" ng-repeat="day in week.days">{{day.number}}</span>
</div>

Das meiste davon ist einfach, aber es gibt ein paar Dinge, die ich besprechen sollte. Zuerst verwenden wir Font Awesome, um die Pfeile zu rendern, mit denen der Benutzer den Monat ändern kann. Font Awesome verwendet eine Reihe von CSS-Klassen, um das Rendering durchzuführen, die in unserem Fall „fa-Winkel-links“ und „fa-Winkel-rechts“ sind, mit einer Basisklasse „fa“ ebenfalls. Sie müssen das I-Tag nicht verwenden, aber so zeigen die Jungs von Font Awesome alle ihre Beispiele, also neige ich dazu, mitzumachen.

Die nächste Zeile zeigt, wie wir Angular JS und Moment verwenden, um den Monat des aktuell ausgewählten Tages zu rendern. In der Monatsvariable speichern wir den Monatswert des Tages. Wir verwenden die Formatfunktion von Moment, um nur den Monatsnamen zu rendern. Beachten Sie, dass der Monat eine vom ausgewählten Datum getrennte Variable ist, da der Benutzer mithilfe der nachlaufenden und führenden Wochen ein Datum außerhalb des ausgewählten Monats auswählen kann. Beispielsweise könnte das Ende eines Monats auf einen Mittwoch fallen, aber wir füllen den Rest der Woche mit Tagen aus dem nächsten Monat auf.

Der letzte HTML-Abschnitt enthält das Rendering für jede der Wochen und Tage. Wir durchlaufen die Liste der Wochen (wie mit der ng-repeat-Direktive von Angular gezeigt) und dann eine weitere Schleife darin, um die Wochentage zu rendern (ein weiterer ng-repeat). Die Syntax für die Direktive ng-repeat ist etwas seltsam, aber einfach. „Woche in Wochen“ gibt an, dass wir über Wochen iterieren und jedes Element im Array „Wochen“ der Variablen „Woche“ zuweisen möchten. Es ist ähnlich wie bei array.forEach Methode. Dann legen wir je nach Status unserer Direktive ein paar Stile für jeden Tag fest. Zum Beispiel möchten wir, dass der ausgewählte Tag und heute einen anderen Stil haben als normale Tage. Wir erreichen dies mit der ng-class-Direktive von Angular, die eine CSS-Klasse für das Element basierend auf einer truthy-Variablen festlegt. Schließlich richten wir eine ng-click-Anweisung ein, mit der wir einen Tag auswählen können.

JavaScript

Hier ist der Angular-Code zum Einrichten der Kalenderdirektive sowie des Controllers für unsere Testseite. Um Verwirrung zu vermeiden, würde ich den Controller und die Direktive in separate Dateien aufteilen, wie es die Best Practice von Angular ist. Der Kürze halber habe ich das gesamte Skript in einem Abschnitt zusammengefasst.

var app = angular.module("demo", []);

app.controller("calendarDemo", function($scope) {
    $scope.day = moment();
});

app.directive("calendar", function() {
    return {
        restrict: "E",
        templateUrl: "templates/calendar.html",
        scope: {
            selected: "="
        },
        link: function(scope) {
            scope.selected = _removeTime(scope.selected || moment());
            scope.month = scope.selected.clone();

            var start = scope.selected.clone();
            start.date(1);
            _removeTime(start.day(0));

            _buildMonth(scope, start, scope.month);

            scope.select = function(day) {
                scope.selected = day.date;  
            };

            scope.next = function() {
                var next = scope.month.clone();
                _removeTime(next.month(next.month()+1)).date(1));
                scope.month.month(scope.month.month()+1);
                _buildMonth(scope, next, scope.month);
            };

            scope.previous = function() {
                var previous = scope.month.clone();
                _removeTime(previous.month(previous.month()-1).date(1));
                scope.month.month(scope.month.month()-1);
                _buildMonth(scope, previous, scope.month);
            };
        }
    };
    
    function _removeTime(date) {
        return date.day(0).hour(0).minute(0).second(0).millisecond(0);
    }

    function _buildMonth(scope, start, month) {
        scope.weeks = [];
        var done = false, date = start.clone(), monthIndex = date.month(), count = 0;
        while (!done) {
            scope.weeks.push({ days: _buildWeek(date.clone(), month) });
            date.add(1, "w");
            done = count++ > 2 && monthIndex !== date.month();
            monthIndex = date.month();
        }
    }

    function _buildWeek(date, month) {
        var days = [];
        for (var i = 0; i < 7; i++) {
            days.push({
                name: date.format("dd").substring(0, 1),
                number: date.date(),
                isCurrentMonth: date.month() === month.month(),
                isToday: date.isSame(new Date(), "day"),
                date: date
            });
            date = date.clone();
            date.add(1, "d");
        }
        return days;
    }
});

Zuerst richten wir die Angular-Anwendung für die Demo ein. Dann richten wir den Controller für die Seite ein und schließlich erstellen wir die Kalenderdirektive. Das Einzige, was wir im Controller tun, ist die Tagesvariable einzustellen, an die der Kalender seinen ausgewählten Tag sendet. Die Kalenderdirektive selbst ist etwas komplexer. Zuerst legen wir einen Startwert für den ausgewählten Tag fest, je nachdem, ob der Tag des Controllers bereits festgelegt ist oder nicht. Ist dies nicht der Fall, verwenden wir einfach das heutige Datum.

Wir gebrauchen Moment um die Zeit auf Mitternacht einzustellen und dann das aktuelle Startdatum für den Anfangsmonat des Kalenders zu generieren. Dann erstellen wir den Monat, indem wir die aufrufen _buildMonth Funktion, die eine Liste von Wochen für den Bereich festlegt. Das wiederum nennt die _buildWeek Funktion, die tagelang dasselbe macht. Das Tagesobjekt enthält Hilfseigenschaften, die verschiedene Dinge angeben, z. B. ob der aktuelle Tag vor dem ausgewählten Monat liegt oder ob der Tag heute ist. Schließlich fügen wir dem Bereich einige Methoden hinzu, die es dem Benutzer ermöglichen, Monate zu ändern und einen Tag auszuwählen. Die select-Funktion ist trivial; Es setzt nur die ausgewählte Variable des Bereichs auf den übergebenen Tag. Die Methoden previous und next dekrementieren bzw. erhöhen den Monat und bauen dann den aktuellen Monat neu auf.

CSS

.vertical-centre (@height) {
    height:@height;
    line-height:@height !important;
    display:inline-block;
    vertical-align:middle;
}

.border-box {
    box-sizing:border-box;
    -moz-box-sizing:border-box;
}

@border-colour:#CCC;
calendar {
    float:left;
    display:block;
    .border-box;
    background:white;
    width:300px;
    border:solid 1px @border-colour;
    margin-bottom:10px;
    
    @secondary-colour:#2875C7;
    @spacing:10px;
    @icon-width:40px;
    @header-height:40px;

    >div.header {
        float:left;
        width:100%;
        background:@secondary-colour;
        height:@header-height;
        color:white;
        
        >* { 
            .vertical-centre(@header-height);
        }
        
        >i {
            float:left;
            width:@icon-width;
            font-size:1.125em;
            font-weight:bold;
            position:relative;
            .border-box;
            padding:0 @spacing;
            cursor:pointer;
        }
        
        >i.fa-angle-left {
            text-align:left;
        }
        
        >i.fa-angle-right {
            text-align:right;
            margin-left:@icon-width*-1;
        }
        
        >span { 
            float:left;
            width:100%;
            font-weight:bold;
            text-transform:uppercase;
            .border-box;
            padding-left:@icon-width+@spacing;
            margin-left:@icon-width*-1;
            text-align:center;
            padding-right:@icon-width;
            color:inherit;
        }
    }
    >div.week {
        float:left;
        width:100%;
        border-top:solid 1px @border-colour;
        
        &:first-child {
            border-top:none;
        }
        
        >span.day {
            float:left;
            width:100%/7;
            .border-box;
            border-left:solid 1px @border-colour;
            font-size:0.75em;
            text-align:center;
            .vertical-centre(30px);
            background:white;
            cursor:pointer;
            color:black;
            
            &:first-child {
                border-left:none;
            }
            
            &.today {
                background:#E3F2FF;
            }
            
            &.different-month {
                color:#C0C0C0;
            }
            
            &.selected {
                background:@secondary-colour;
                color:white;
            }
        }
        
        &.names>span {
            color:@secondary-colour;
            font-weight:bold;
        }
    }
}

Die ersten paar Zeilen definieren ein paar hilfreiche Mixins mit LESS CSS. Die erste ermöglicht es uns, Elemente vertikal zu zentrieren, vorausgesetzt, wir haben die Höhe des Umhüllungselements. Die zweite legt die Box-Sizing-Eigenschaft fest, die Firefox ohne das Präfix -moz- nicht unterstützt.

Als Nächstes legen wir einige Variablen fest, die sich auf Stil und Abstände beziehen, die mehr als einmal verwendet werden. Wenn Sie beispielsweise die Farbe ändern möchten, müssen Sie die Sekundärfarbenvariable aktualisieren. Der Rest ist nur Standard-Styling, damit der Kalender etwas hübsch aussieht, und Abstandshalter, um sicherzustellen, dass er richtig ausgerichtet ist.

Fazit

Und das ist es! Wie oben erwähnt, habe ich eine Demoseite zusammengestellt, die den Kalender in seiner endgültigen Form zeigt. Du kannst es sehen hier.

Danke fürs Lesen!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *