Download - MVS: An angular MVC
![Page 1: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/1.jpg)
FRONT MVC@DRPICOX
![Page 2: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/2.jpg)
THINGS WRONG THAT I DID TO FIT THINGS IN SLIDES
DISCLAIMER
• Directives should use controller and bindToController
• Directives should never load resources, this should be done by routes or under demand
• Use .factory to simplify and homogenize code (not .service neither .value)
• In a previous talk I said that model was plain JS data, sorry (plain data is the form, but does not defines a model)
• Use better variable names
![Page 3: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/3.jpg)
MVC - MODEL THE GREAT FORGOTTEN
FRONT MVC
![Page 4: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/4.jpg)
TYPICAL ANGULAR CODE
AS SEEN ON SOME DOCS (AND FROM SOME BEGINNERS)
![Page 5: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/5.jpg)
TYPICAL ANGULAR CODE<APP-BOOKS-LIST>
app.component(‘appBooksList’, { template: ‘…’, controller($http) { $http.get(‘/api/v1/books’).then(response => { this.books = response.data; }); }, });
![Page 6: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/6.jpg)
TYPICAL ANGULAR CODE<APP-SCI-FI -BOOKS-LIST>
app.component(‘appSciFiBooksList’, { template: ‘…’, controller($http) { $http.get(‘/api/v1/books’).then(response => { this.books = response.data.filter(isSciFi); }); }, });
![Page 7: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/7.jpg)
REFACTORING - SERVICE
THERE IS REPLICATED CODE ¡LET’S DO A SERVICE!
![Page 8: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/8.jpg)
REFACTORING - SERVICEbooksService
app.service(‘booksService’, ($http) => { this.getList = () => { return $http.get(‘/api/v1/books’).then(function(response) { return response.data; }); }; });
Acquires the responsibility for: • R1: Know the API context Url • R2: Create a remote connection • R3: Transform response into usable object
![Page 9: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/9.jpg)
REFACTORING - SERVICE<APP-BOOKS-LIST> & <APP-SCI-FI -BOOKS-LIST>
app.component(‘appBooksList’, { template: ‘…’, controller(booksService) { booksService.getList().then(books => { this.books = books; }); }, });
app.component(‘appSciFiBooksList’, { template: ‘…’, controller(booksService) { booksService.getList().then(books => { this.books = books.filter(isSciFi); }); }, });
![Page 10: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/10.jpg)
PERFORMANCE - CACHING
OPS! WE ARE LOADING DATA TWICE ¡LET’S DO A CACHE!
![Page 11: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/11.jpg)
PERFORMANCE - CACHINGbooksService
Notice that: • Repairs all directives at once • Acquires one new responsibility (R4: manage cache)
app.service(‘booksService’, ($http) => { this.getList = () => { return $http.get(‘/api/v1/books’, {cache:true}).then(response => { return response.data; }); }; });
![Page 12: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/12.jpg)
PERFORMANCE - CACHINGbooksService
Notice that: • Repairs all directives at once • Acquires one new responsibility (R4: manage cache)
app.service(‘booksService’, ($http) => { this.getList = () => { if (!this.list) { this.list = $http.get(‘/api/v1/books’).then(response => { return response.data; }); } return this.list; }; });
Alternate
![Page 13: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/13.jpg)
NEW FEATURE - ONE BOOK
WE HAVE A VIEW THAT ONLY SHOWS ONE BOOK
![Page 14: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/14.jpg)
NEW FEATURE - ONE BOOK<APP-BOOK-VIEW BOOK-ID=“ID”>
app.component(‘appBookView’, { template: ‘…’, bindings: { bookId: ‘<‘ }, controller: function(booksService) { booksService.get(this.bookId).then(book => { this.book = book; }); }, });
![Page 15: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/15.jpg)
NEW FEATURE - ONE BOOKbooksService (step1)
Notice that: • What about repeating loading of books (R4: manage cache)
app.service(‘booksService’, ($http) => { this.loadAll = function() { return $http.get(‘/api/v1/books’, {cache:true}).then(response => { return response.data; }); }; this.load = (id) => { return $http.get(‘/api/v1/books/’+id).then(response => { return response.data; }); }; });
![Page 16: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/16.jpg)
NEW FEATURE - ONE BOOKbooksService (step2)
• Uhmmmm… about R4… managing caches
app.service(‘booksService’, ($http) => { this.loadAll = function() { return $http.get(‘/api/v1/books’, {cache:true}).then(response => { return response.data; }); }; this.load = (id) => { return $http.get(‘/api/v1/books/’+id, {cache:true}).then(response => { return response.data; }); }; });
![Page 17: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/17.jpg)
NEW FEATURE - ONE BOOK
WE ARE LOADING TWICE THE SAME BOOK!
It happens when: • Loading one book • Loading all books
![Page 18: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/18.jpg)
NEW FEATURE - ONE BOOK
OK… MAY BE IT’S OK LOAD TWICE BUT NOT MORE TIMES
THE SAME BOOK
“We keep it simple…”
![Page 19: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/19.jpg)
NEW FEATURE - UPDATE BOOK
WE HAVE A VIEW THAT MAKES AN UPDATE OF A BOOK AND SHOWS THE CHANGES INTRODUCED BY API
![Page 20: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/20.jpg)
NEW FEATURE - UPDATE BOOK<APP-BOOK-UPDATE BOOK-ID=“ID”>
app.component(‘appBookUpdate’, { template: ‘…’, bindings: { bookId: ‘<‘, } constructor(booksService) { booksService.load(this).then(book => { this.book = book; }); this.update = () => { booksService.update(this.book).then(updatedBook => { this.book = updatedBook; }); }; }; });
![Page 21: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/21.jpg)
NEW FEATURE - ONE BOOKbooksService (step2)
• Uhmmmm… about R4… managing caches
app.service(‘booksService’, ($http) => { this.getList = () => { return $http.get(‘/api/v1/books’, {cache:true}).then(response => { return response.data; }); }; this.get = (id) => { return $http.get(‘/api/v1/books/’+id, {cache:true}) .then(response => { return response.data; }); }; this.update = (book) => { return $http.put(‘/api/v1/books/’+book.id) .then(function(response) { return response.data; }); }; });
![Page 22: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/22.jpg)
NEW FEATURE - UPDATE BOOK
SHIT!
![Page 23: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/23.jpg)
NEW FEATURE - UPDATE BOOK
SHIT!
What about: • Cache? • What if we have a list side-by side, it is updated? • What if we have view and update side-by-side?
![Page 24: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/24.jpg)
NEW FEATURE - UPDATE BOOK
SHIT!
How to solve it? • New services? • Callbacks? • RxJS? • More caches? • Events?
![Page 25: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/25.jpg)
NEW FEATURE - UPDATE BOOK
WHAT IS THE REAL PROBLEM?
![Page 26: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/26.jpg)
NEW FEATURE - UPDATE BOOK
WHAT IS THE REAL PROBLEM?
R4 (manage caches) is hidden another responsibility: • Single source of true
We need a model!
![Page 27: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/27.jpg)
WHAT A MODEL IS NOT?
• A model is not styles in the web
• A model is not objects in the scope
• A model is not objects stored in the browser (local,websql,…)
• A model are not instances of any sort of data
• A model is not plain data
![Page 28: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/28.jpg)
SINGLE SOURCE OF TRUE
WHAT IS A MODEL?
• You can find your model
• There is only one instance for each “concept” (all books with the same id are the same object)
• Models may be computed from other models
• It does not matters how many views do you have, all views use the same models (as do services also)
That is something that ember programmers knows very well.
![Page 29: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/29.jpg)
REFACTOR - ADD MODELBook
app.value(‘Book’, function Book(id) { this.id = id; this.isSciFi = function() { return !!this.tags.sciFi; }; this.takeData = function(bookData) { angular.extend(this, bookData); }; });
We discover new responsibilities: • R5: update and extract information of a book
![Page 30: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/30.jpg)
REFACTOR - ADD MODELbooksDictionary
app.value(‘booksDictionary’, (Book) => { this.list = []; this.map = {}; this.getOrCreate = (id) => { var book = this.map[id]; if (!book) { book = new Book(id); this.list.push(book); this.list.map[id] = book; }; return book; }; this.takeDatas = (bookDatas) => { bookInfos.forEach((bookData) => { this.getOrCreate(bookData.id).takeData(bookData); }); }; });
We discover new responsibilities: • R6: manage book instances to avoid replicates • R7: store books so anyone can access to them
Note that listis also a model.
![Page 31: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/31.jpg)
booksService (loadAll)
app.service(‘booksService’, (booksDictionary, $http) => { this.getList = () => { if (!this.list) { this.list = $http.get(‘/api/v1/books’).then(response => { booksDictionary.takeDatas(response.data); return booksDictionary.list;
}); } return this.list; }); }; … });
REFACTOR - ADD MODEL
getList returns always the same instance of list.
![Page 32: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/32.jpg)
booksService (load)
app.service(‘booksService’, (booksDictionary, $http) => { … this.books = {}; this.load = (id) => { if (!this.books[id]) { this.books[id] = $http.get(‘/api/v1/books/’+id).then(response => { var book = booksDictionary.getOrCreate(id); book.takeData(reponse.data); return book; }); } return this.books[id]; }; … });
REFACTOR - ADD MODEL
Load(id) returns always the same instance of book for the same id. And the instance will be contained by the list in getList.
![Page 33: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/33.jpg)
booksService (update)
app.service(‘booksService’, (booksDictionary, $http) => { … this.update = (book) => { var id = book.id; this.books[id] = $http.put(‘/api/v1/books/’+id).then(response => { var book = booksDictionary.getOrCreate(id); book.takeData(response.data); return book; }); }; });
REFACTOR - ADD MODEL
Update returns always the same instance than get and getList, regardless the input. And also updates the same instance.
![Page 34: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/34.jpg)
three layers
REFACTOR - ADD MODEL
SERVICES
MODELS VIEWS
callsupdates
are $watched
![Page 35: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/35.jpg)
NEW FEATURE - UPDATE BOOK
DONE!
![Page 36: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/36.jpg)
NEW FEATURE - UPDATE BOOK
DONE?
What about Sci-Fi list? • Is computed:
it has to be recomputed each time that a book o list changes
• A filter is expensive • Watch a derive function is expensive • Watch all books (aka $watch(,,true)) is expensive
![Page 37: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/37.jpg)
NEW FEATURE - UPDATE BOOK
SHIT!
Solved in the next talk…
![Page 38: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/38.jpg)
MVS: MVC IN ANGULAR
FRONT MVC
![Page 39: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/39.jpg)
three kinds of components
ORIGINAL MVC
CONTROLLERS
MODELS VIEWS
are listenedupdates
are observed
![Page 40: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/40.jpg)
the truth
ORIGINAL MVC
MODELS VIEWSknows and queries
are listenedupdates
are observed
knows and queries
CONTROLLERS
![Page 41: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/41.jpg)
ORIGINAL MVC
SHIT!
![Page 42: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/42.jpg)
ORIGINAL MVC
SHIT!
It is not as beautiful and easy as it seems. May be it worked in ’78, with just few Kb… and low complexity, but now…
![Page 43: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/43.jpg)
FB comments about MVC
ARCHITECTURES VARIATIONS
https://youtu.be/nYkdrAPrdcw?t=10m20s
![Page 44: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/44.jpg)
FB comments about MVC
ARCHITECTURES VARIATIONS
“MVC works pretty well for small applications…
but it doesn’t make room for new features.”
“Flux is a single direction data flow, that avoids all the arrows
going on all directions what makes really
hard to understand the system.”
![Page 45: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/45.jpg)
FB comments about MVC
ARCHITECTURES VARIATIONS
“Let’s see a real good example: FB chat”
“How we get to the point, so we were annoying our users so much the just they wanted us to fix chat?”
“The problems here were: • The code has no structure • It was very imperative, that makes it fragile • It loose a lot of the original intend behind it, its hard to tell what it tries [to do] • Add more features only gets this code larger • We had our most annoying chat bug happen over and over • We were always fixing some pretty good edge case, the whole system was fragile • … • This code becomes more fragile with the time. • No member of the team wanted to touch it, they wanted to jump to any other bug.”
![Page 46: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/46.jpg)
f lux
ARCHITECTURES VARIATIONS
![Page 47: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/47.jpg)
AND COMMUNITY ALSO CONTRIBUTED…
ARCHITECTURES VARIATIONS
![Page 48: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/48.jpg)
redux
ARCHITECTURES VARIATIONS
![Page 49: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/49.jpg)
cyclejs
ARCHITECTURES VARIATIONS
![Page 50: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/50.jpg)
Key points are:
• Single direction flow
• Avoid imperative code
• Decoupled state from views
• Computed data consistency (example: cart.price = ∑item.price * item.quantity)
ARCHITECTURES VARIATIONS
![Page 51: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/51.jpg)
mvc
FROM MVC TO MVS
MODELS VIEWSknows and queries
are listenedupdates
are observed
knows and queries
CONTROLLERS
![Page 52: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/52.jpg)
mvc-angular
FROM MVC TO MVS
MODELS VIEWSknows and queries
are $watched
CONTROLLERS
![Page 53: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/53.jpg)
the same f low
FROM MVC TO MVS
SERVICES
MODELS VIEWS
callsupdates
are $watched
![Page 54: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/54.jpg)
MVS RULES (I)
SERVICES
MODELS VIEWS
calls
updates
are $watched
• Views can call to services
• Services manages models
• Models are watched by views through $watch
• Views cannot modify models but temporary copies
• Each services has its own models and do not modify other services models
![Page 55: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/55.jpg)
Key points are:
• Single direction flow
• Avoid imperative code
• Decoupled state from views
• Computed data consistency (example: sciFiBooks = books.filter(isSciFi))
ANGULAR MVS
![Page 56: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/56.jpg)
SOLUTION FOR SCI-FI-BOOKS
• Create a new model for SciFiBooks
• Add a method getSciFiBooks() to bookService
• Recompute the list each time that an update() method is called
![Page 57: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/57.jpg)
BUT!
SOLUTION FOR SCI-FI-BOOKS
![Page 58: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/58.jpg)
BUT!
It does not scale. ¿What happens with more kind of books? ¿What happens with more complex data?
SOLUTION FOR SCI-FI-BOOKS
![Page 59: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/59.jpg)
SOLUTION FOR SCI-FI-BOOKS
• We need a synchronization mechanism
• ex: events or observables
![Page 60: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/60.jpg)
SOLUTION FOR COMPUTED VALUES
MODELS
• Models launch update: ex $broadcast(‘booksChanged’)
for angular1
fire events
![Page 61: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/61.jpg)
SOLUTION FOR COMPUTED VALUES
MODELS
• Models launch update: ex $broadcast(‘booksChanged’)
• Rules:
• Each model has its own event (1 <-> 1)
• We do not pass any information (ex: previous and new value)
• Change event is fired by the Service that manages the model
• Events can be debounced (multiple collapsed in one)
rules
fire events
![Page 62: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/62.jpg)
booksService (update)
app.service(‘booksService’, (booksDictionary, $http, $broadcast) => { … this.update = (book) => { var id = book.id; this.books[id] = $http.put(‘/api/v1/books/’+id).then(response => { var book = booksDictionary.getOrCreate(id); book.takeData(response.data); $broadcast(‘booksChanged’); return book; }); }; });
SOLUTION FOR SCI-FI-BOOKS
![Page 63: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/63.jpg)
<APP-SCI-FI -BOOKS-LIST> (update)
SOLUTION FOR SCI-FI-BOOKS
app.component(‘appSciFiBooksList’, { template: ‘…’, controller(booksService, $scope) { getSciFiBooks(); $scope.$on(‘booksChanged’, getSciFiBooks);
function getSciFiBooks() { booksService.getList().then(books => { this.books = books.filter(isSciFi); }); } }, });
![Page 64: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/64.jpg)
<APP-SCI-FI -BOOKS-LIST> (update)
SOLUTION FOR SCI-FI-BOOKS
app.component(‘appSciFiBooksList’, { template: ‘…’, controller(booksService, $scope) { getSciFiBooks(); $scope.$on(‘booksChanged’, getSciFiBooks);
function getSciFiBooks() { booksService.getList().then(books => { this.books = books.filter(isSciFi); }); } }, });
It smells to a service function…
![Page 65: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/65.jpg)
sciFiBooksService (update)
app.service(‘sciFiBooksService’, (booksService, $rootScope) => { this.list = []; this.getList = () => this.list; updateList(); $rootScope.$on(‘booksChanged’, updateList); function updateList() { booksService.getList().then(books => { angular.copy(books.filter(isSciFi), this.list); $broadcast(‘sciFiChanged’); }); } });
SOLUTION FOR SCI-FI-BOOKS
![Page 66: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/66.jpg)
<APP-SCI-FI -BOOKS-LIST> (update)
SOLUTION FOR SCI-FI-BOOKS
app.component(‘appSciFiBooksList’, { template: ‘…’, controller(sciFiBooksService, $scope) { sciFiBooksService.getList().then(books => { this.books = books; }); }, });
![Page 67: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/67.jpg)
<APP-SCI-FI -BOOKS-LIST> (update)
SOLUTION FOR SCI-FI-BOOKS
app.component(‘appSciFiBooksList’, { template: ‘…’, controller(booksService, $scope) { getSciFiBooks(); $scope.$on(‘booksChanged’, getSciFiBooks);
function getSciFiBooks() { booksService.getList().then(books => { this.books = books.filter(isSciFi); }); } }, });
It smells to a service function…
![Page 68: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/68.jpg)
Hierarchy
SOLUTION FOR SCI-FI-BOOKS
book Service
sciFiBooks Service
is listened
calls
Main Rule: no cycles of the arrow same color
![Page 69: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/69.jpg)
Hierarchy
SOLUTION FOR SCI-FI-BOOKS
product Service
Main Rule: no cycles of the arrow same color
showroom Service
user Service
cart Service
shipping Service
payment method Service
addresses Service
![Page 70: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/70.jpg)
MVS: MVC IN ANGULAR
FRONT MVC
![Page 71: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/71.jpg)
the same f low
MVS
SERVICES
MODELS VIEWS
callsupdates
are $watched
![Page 72: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/72.jpg)
the same f low
MVS
SERVICES
MODELS VIEWS
calls
updates
are $watched
Dumb Views
Smart Views
BROWSER
uses listens
uses listens
![Page 73: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/73.jpg)
the same f low
MVS
SERVICES
MODELS VIEWS
calls
updates
are $watched
Dumb Views
Smart Views
BROWSER
uses listens
uses listens
Services
Remotes Storages
callscalls
![Page 74: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/74.jpg)
the same f low
MVS
SERVICES
MODELS VIEWS
calls
updates
are $watched
Dumb Views
Smart Views
BROWSER
uses listens
uses listens
Services
Remotes Storages
callscalls
State Holders
State Singletons
State Dictionaries
CI
CI
CICICI
![Page 75: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/75.jpg)
computed data f low
MVS
SERVICES
MODELS VIEWS
calls
updates
are $watched
Dumb Views
Smart Views
BROWSER
uses listens
uses listens
Services
Remotes Storages
callscalls
State Holders
State Singletons
State Dictionaries
CI
CI
CICICI
![Page 76: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/76.jpg)
computed data f low
MVS
SERVICES
MODELS VIEWS
calls
updates
are $watched
Dumb Views
Smart Views
BROWSER
uses listens
uses listens
Services
Remotes Storages
callscalls
State Holders
State Singletons
State Dictionaries
CI
CI
CICICI
are listened
are listened
![Page 77: MVS: An angular MVC](https://reader031.vdocuments.us/reader031/viewer/2022021507/58eccda81a28ab3a768b4681/html5/thumbnails/77.jpg)
step by step
COMPUTED DATA FLOW
1. call
5. is fired
Books Service
Books Dictionary
Sci-Fi Service
Sci-Fi Dictionary
2. updates
3. fire $update
7. updates
8. fire $update
$UPDATE EVENT MANAGER
4. fire $update
6. reads