Binding Data in Angular 2 (ES5) - javascript

I am having trouble using data model binding in Angular 2.0 written in ES5 Javascript. I created a ToDo list following the Angular tutorial and various other sources, but I was not successful when trying to add ToDo items from an asynchronous request (either from a db or just added an item after a request is made).
The data will update, but it won't show up in the DOM until I call an $event or somehow force Angular or Zone.js to go through another cycle.
Also, the only browser that this plunker works in is Chrome, so I'm not sure what is wrong there either.
Any help on any of those things would be appreciated!
Here is the plunker: http://plnkr.co/edit/p3Ipvw4SNut0XLOn76kJ?p=preview

It's a bug in Angular2 alpha. It's resolved and committed, but has not made its way to a release yet.
https://github.com/johnpapa/angular2-tour-of-heroes/issues/24

Related

Angular 1.x migration performance issues

I am upgrading a huge angular 1 project from 1.3.x to 1.6.x because we require some patches in the latest version. After updating it seems that the entire application has slowed dramatically. I have been looking through the migration documentation but is there anything that could be causing major slow downs? Any bad code or gotchas that would cause this? I am having issues just with visual changes such as ng-show and ng-hide being slow and twitchy.
This is the CPU profile before upgrade:
This is the CPU profile after upgrade:
Thank you!
EDIT:
Let me give a little more context. I have a feeling this has to do with the digest cycle. For example, I a navbar where an icon will hide and another will show on hover.
Here is what it looks like in angular 1.3
Here is what it looks like in angular 1.6
I am getting a forced reflow performance warning after the update. Also this (recalculate style) is directed from angular-animate s computeCssStyles function (or at least that is the line of code it's directing me towards). I am also not calling any of $animate in my code. Is this just a product of the angular digest method? Also is there anything that I am missing from the migration docs about possible changes to digest?
Code example:
showDropdown is changed from false to true on hover and visa versa.
<i> ng-show="! showDropdown" </i><i> ng-show="showDropdown" </i>
EDIT:
Short term fix as I am not using animate anywhere in my code but it seems to be firing as per the newer angular digest method. I just disabled animations as a partial short term fix.
$animate.enabled(false);
Managing memory is difficult in JavaScript. Here are few best practices to improve the performance in terms of loading pages and freeing memory.
Removing Detached Node manually - Work on to remove detached object.
var myNode = document.getElementById("bodyPanel");
if(myNode !== null){
while (myNode.firstChild) {
myNode.removeChild(myNode.firstChild);
}
}
On every page switch, call destroy inside Angularjs controller. Also javaScript object Reference to null
$scope.$on("$destroy",function() {
$window.off("resize.Viewport");
});
Create Angular js Service to keep important data in memory to avoid fetching from HTML5 storage system.
As mentioned in comment, use ng-if instead of ng-show.

ExtJS Ext.state.Manager.setProvider() behavior in 6.2 vs 4.x

I have an existing ExtJS application I'm upgrading from 4.x to 6.2.0. I had a simple storage provider setter that I pass into my Ext.onReady() block that looks like the following:
Ext.state.Manager.setProvider(Ext.create('Ext.state.LocalStorageProvider',{}));
When I swapped to 6.2.0, I'd get the error:
ext-all-rtl-debug.js:9389 [E] Ext.util.LocalStorage.constructor(): Cannot create duplicate instance of local store "ext". Use Ext.util.LocalStorage.get() to share instances.
So what I had to do to, what I think is a fix, was the following:
Ext.state.Manager.setProvider(Ext.util.LocalStorage.get('id'));
My concern here though is that I'm just applying a bandaid to the problem and not really going through with a real fix. I don't explicitly set the provider anywhere else, all I did was swap out the ExtJS lib from 4.x to 6.2.0 to get that error. It's as-if it's being created somewhere else first in the 6.2.0 initialization process and now I'm getting a duplicate error as aforementioned.
What has changed in 6.2.0 to cause this behavior? Is there now two providers set, one by ExtJS and one with my client code? Is there a cleaner way of handling this?
The preconditions for this error are the same in both, ExtJS 4 and ExtJS 6. The corresponding file does not have changed: compare ExtJS 4.2.4 version and ExtJS 6.2.0 version.
Because of this your application must be responsible for this. Somewhere in your (upgraded) code an instance of Ext.util.LocalStorage must be created. Since this error is thrown in case the ID is already registered and the registration is done only in the constructor of the Ext.util.LocalStorage class, I'd suggest to set a breakpoint right there to check in the stacktrace which function does call the constructor method.

Using SailsJS sails.io with Angular 2

Is there a way to instantiate sails.io inside the zone of a service provider in Angular2 so that websocket events trigger change detection?
A sub-question: how to RXJS to subscribe to sails.io data streams.
I'm using Angular2 RC4, and the latest version of SailsJS.
Related question: Angular2 View Not Changing After Data Is Updated
UPDATE
It annoyed me that I couldn't give a full example of how to use Sails with Angular 2 with just plunker, so I created a github repo, that provides the full picture on how this can work.
I can see how the related question you linked, would lead you down the zone path. However, you can plug all of this together without having to manually tinker with zones. Here is an example of how you could implement sails.io with Angular2 in a plunker. This leverages using RxJS to create a type of observable. You also have to implement a different version of Angular2 change detection(all of this is implemented in the plunker).
I go into a little more detail in my answer to your linked question.
As for your sub question I'm not sure if there is a way to integrate the stream, I believe one of the intentions of RxJS was to reduce the use of callbacks, which sails.io appears to still do.
Excerpt of implementing sails.io in a service from the plunker.
constructor() {
this._ioMessage$ = <Subject<{}>>new Subject();
//self is the window object in the browser, the 'io' object is actually on global scope
self.io.sails.connect('https://localhost:1337');//This fails as no sails server is listening and plunker requires https
this.listenForIOSubmission();
}
get ioMessage$(){
return this._ioMessage$.asObservable();
}
private listenForIOSubmission():void{
if(self.io.socket){//since the connect method failed in the constructor the socket object doesn't exist
//if there is a need to call emit or any other steps to prep Sails on node.js, do it here.
self.io.socket.on('success', (data) => {//guessing 'success' would be the eventIdentity
//note - you data object coming back from node.js, won't look like what I am using in this example, you should adjust your code to reflect that.
this._ioMessage$.next(data);//now IO is setup to submit data to the subscribbables of the observer
});
}
}

Ember UI not triggering Ember controller actions during testing

I have quite an interesting problem.
We have Rails + Capybara performing integration tests with our Ember frontend.
The issue I'm having is, when running our :Selenium powered tests, SOMETIMES (and this is the crucial bit, it's sometimes), a UI element will be pressed and the Ember action will NOT fire.
So, This is NOT an ajax related issue. I'm not getting a data error. Nor an Ember error, nor a js error, nor a Capybara::ElementNotFound error.
The UI in question has loaded, Capybara then successfully clicks on the button, and then the Ember action is never called. It's not that it's taking too long to respond, it's simply not triggered.
I know this because I'm logging the Ember actions (console.log()) and can see it happen when it works, and not happen when it doesn't.
So, my theory is... Ember has loaded the UI before it's setup all the js to handle the actions. Could this be possible?
Have you tried explicitly triggering the run loop in your tests?
Figured it out.
It seems as if the Ember templates, and thus UI, will load BEFORE all methods in the setupController property in Routers is complete.
I don't really know enough about Ember to understand how and why this works like this, but I was able to fix this issue by doing the following:
At the end of all callbacks in setupController I set a controller property to true. 'controller.set('setupDone', true)'
In the template for that Route, I wrap the UI in a conditional {{#if setupDone}}

Attempted to handle event `willCommit` on while in state root.loaded.updated.inFlight

I'm learning how to use EmberJS by doing the introductory tutorial form the "Getting started" page. However, when I get to the "Accepting edits" part, I have a bug:
Uncaught Error: Attempted to handle event `willCommit` on <Todos.Todo:ember304:3> while in state root.loaded.updated.inFlight.
The call to Todos.TodoController.acceptChanges() seems to be triggering that error. The part I'm referring about is this one:
http://emberjs.com/guides/getting-started/accepting-edits/
After reading up on model lifecycle in Ember - http://emberjs.com/guides/models/model-lifecycle/#toc_in-flight - I still don't get why this bug appears.
One work-around is to save the model each time it changes (so every time the value of the <input> changes. Which works fine but would probably perform poorly with a HTTP API (as opposed to fixtures).
Could this be due to BC breaking changes in the ember-data lib?
What else could cause this?
Versions of libraries I've used:
jQuery: 2.0.3
Handlebars 1.0.0
EmberJS: 1.0.0 RC7
Ember Data: v0.13-102-g6bdebe7
After reading up on model lifecycle in Ember - http://emberjs.com/guides/models/model-lifecycle/#toc_in-flight - I still don't get why this bug appears.
This is not a bug, the in-flight section say's it all:
A record that is in-flight is a dirty record that has been given to the adapter to save the changes made locally. Once the server has acknowledged that the changes have been saved successfully, the record will become clean.
This means that you are trying to change the record while a previously change made it dirty and a possibly call to this.get('store').save() is still in the doings e.g. waiting for the server to respond. During this time frame you can't make changes to that same record without getting the error.
So a solution could be to not trigger this.get('store').save() after a character of the textbox has changed but rather on focus out for example, or even with a explicit button to save the record which you could disable until your server acknowledges it's change, this would not make a request for every character to the server resulting in sluggish performance due to some latency. Hope this makes sense.
Hope it helps.
I had this same issue with the Getting Started guide. I solved it by checking if the model was currently saving in acceptChanges:
acceptChanges: function() {
var model = this.get('model')
if (model.get('isSaving')) { return }
this.set('isEditing', false)
model.save()
}

Categories