W naszej tworzonej aplikacji AgendaEditor, możemy wpisywać dane poprzez pola tekstowe w formularzu. Jednak po odświeżeniu strony wszystkie dane zostają usuwane. Nie będziemy jeszcze teraz implementować zapisu danych do bazy danych. Ale chcielibyśmy, aby użytkownik miał możliwość importu i eksportu danych z/do aplikacji.
Na początek wybrałem dane w formie tekstowej, oddzielone tabulatorami. Dlaczego? Bo jeśli mamy dane w Excelu, to po ich skopiowaniu automatycznie wstawiane są tabulatory, aby oddzielić od siebie kolumny. Jeśli mamy dane w takiej formie (oddzielone tabulatorami), to po wklejeniu do Excela, zostaną poprawnie wklejone w oddzielne wiersze i kolumny. Dzięki temu będziemy mogli swobodnie przenosić dane pomiędzy aplikacją AgendaEditor a Excelem.
Struktura danych ma odpowiadać formularzowi. Jeden wiersz ma mieć postać:
tytuł imię nazwisko czas_wystąpienia
Oczywiście wierszy może być więcej (kolejne wystąpienia na liście). Przykładowo:
Programowanie Jan Kowalski 00:20 AngularJS Anna Nowak 00:25
Formularz importu/eksportu w HTML
W pliku import.html
dodajemy wielowierszowe pole tekstowe textarea
:
1 2 3 4 5 6 7 |
<form> <div class="form-group"> <label>Wklej lub skopiuj dane oddzielone tabulatorami (tak po skopiowaniu z Excela).</label> <textarea class="form-control" rows="6" placeholder="tytuł imie nazwisko 00:15" ng-model="agenda.byTabs" ng-model-options="{getterSetter: true}"></textarea> </div> </form> |
Ustawiamy dla niego model dyrektywą ng-model
. Skorzystamy z getterów i setterów, tak jak w tym wpisie. Dlatego też musimy włączyć ich obsługę za pomocą dyrektywy ng-model-options
. Dane wklejane do tego pola tekstowego będą automatycznie aktualizować model w aplikacji. Jak również modyfikacja modelu (np. poprzez poprzedni formularz) będzie aktualizować zawartość tego pola.
Kontroler w JavaScript
Dlatego potrzebne nam dodatkowe pole z getterami i setterami (które będą konwertować dane z modelu na tekst z tabulatorami) w naszym serwisie Agenda. W pliku import.js
po prostu korzystamy z serwisu:
1 2 3 |
.controller('importController', function($scope, Agenda) { $scope.agenda = Agenda; }); |
Serwis Agenda w JavaScript
Przejdźmy zatem do naszego serwisu w pliku agenda.js
. Dodajemy w nim nowe pole z getterem i setterem:
1 2 3 4 5 6 7 8 9 10 11 |
this.byTabs = function(newImport) { if(arguments.length) { // setter // ... return byTabs; } else { // getter // ... return byTabs; } } |
Implementacja settera
W zmiennej newImport
mamy zawartość wielowierszowego pola tekstowego z danymi do agendy oddzielonymi tabulatorami.
Najpierw musimy podzielić wszystko na osobne linie za pomocą metody split
(jako separator podajemy znak nowej linii \n
).
Następnie w pętli przechodzimy po wszystkich liniach. Wrzucamy na pustą listę z danymi kolejne rekordy. Żeby mieć do nich dostęp, należy linię podzielić z separatorem tabulator \t
.
1 2 3 4 5 6 7 8 9 |
// setter var lines = newImport.split("\n"); byTabs = newImport; this.list = []; for (var i = 0; i < lines.length; i++) { var fields = lines[i].split("\t"); this.list.push({title: fields[0], name: fields[1], surname: fields[2], time: fields[3]}); } return byTabs; |
Implementacja gettera
Przechodzimy po liście z danymi i przepisujemy każde pola do jednego stringa oddzielając je tabulatorami \t. Zaś kolejne rekordy oddzielamy znakami nowego wiersza \n (opuszczamy ostatni znak nowej linii, żeby nie wstawiać pustej linii na końcu wszystkich rekordów).
1 2 3 4 5 6 7 8 9 |
// getter byTabs = ""; for (var i = 0; i < this.list.length; i++) { if(isNotEmptyRecord(this.list[i])) { byTabs += this.list[i].title + "\t" + this.list[i].name + "\t" + this.list[i].surname + "\t" + this.list[i].time; byTabs += i == this.list.length-1 ? "" : "\n"; } } return byTabs; |
Pingback: Drag & drop w AngularJS | Marcin Kowalczyk – Blog IT