multiple textareas using angular ui-tinymce not displaying when using two controllers - angularjs

I am using ui-tinymce with angular 1.5 and am using it in two different locations on the page coming from two separate controllers. It will only work on one textarea at at time.
If i move both textareas to the same controller they display correctly. Or if i delete one textArea the other displays. Is there anything special needed to make ui-tinymce work from two controllers on one page? I am injecting ui-tincymce into both controllers.
Thank

I ran into the same issue and determined the reason is because the directive starts its ID numbering at 0 for each controller. (see var generatedIds = 0 in angular.tinymce.js on or around line 8). Someone with more under-the-hood knowledge of Angular could explain why the directive "resets" for every controller, but the root issue is that the directive is reusing IDs. The fix I came up with is to modify angular.tinymce.js to replace:
attrs.$set('id', ID_ATTR + '-' + generatedIds++);
with
attrs.$set('id', ID_ATTR + '-' + String(new Date().getTime());
It's not ideal but it fixed my issue immediately. getTime() is milliseconds since Jan 1 1970, so it counts up quite rapidly (meaning, the chances of a collision are extremely slim). You could combine this with something like + String(Math.round(Math.random() * 100000)) if you're truly paranoid that your JavaScript might run fast enough (or threaded enough, someday) to initialize two tinymce editors on the same millisecond.

Related

Is it worth to build a web application combining AngularJs and ReactJs components

I have web application that is written in AngularJs 1.x so i have decided to convert it into either AngularJs2 or ReactJs+AngualrJs2. Reason to choosed ReactJs was that it is rendered faster than AngualrJs and i choosed AnguarJs was that it's two way data binding and i can keep my legacy model as it is and data bind into ReactJs components.I prefer AngualrJs data model over flux.I am deciding to create reuslable HTML components in ReactJs and bind AngularJs model data into it.
Sample Code Snippet using AngualrJs + ReactJs
angular.module('app').directive('greeting',[function(){
return {
restrict:'AE',
scope:{name:'#'},
link: function (scope, elem, attrs){
var GreetingSection = React.createClass({displayName: 'Greeting',
render: function() {
var message = "Good morning " + this.props.data.name + ", how are you?";
return React.createElement('div', {className: "greeting"},message);
}
});
React.renderComponent(GreetingSection({data:scope}), elem[0]);
}
};
}]);
My questions are,
Are there any performance benefits if i combined AngualrJs(2.x or 1.x) with ReactJs components?
Can i achieve faster rendering using AngularJs 2.x without ReactJs?
Please help me to take an decision.
Trying to answer generally
Analysis :
Note : i have used both
Remember on all performance post on internet there is MICRO seconds difference & people start shouting "this is fast".."that is slow" ... you could notice.Both are having cutthroat performance
so if you really worried about performance then try to categorize your app based on below criteria .
so that you don't mess up loading "angular 10 libs" + "react 10 libs" = 20 libs on ui , without analyzing
Angular category
Famous for two way data binding
Best for lots of data computation on UI Eg -
rate * quantity = amount
Its stubborn(typed lang,framework driven) for creating components.
React category
Famous for component simplicity & rendering
Best for lots of visual changes on UI Eg : adding bulk markers on map
Worst for lots of data computation on UI Eg -
rate * quantity = amount.So if you miss 1 setState() and final computation will be wrong
Confusion :
So if person wants to use both then person have not defined his use case clearly,As after using both libraries he will be adding extra dozens of libraries which will slow down app from other side
So if person chooses only 1 than he is on very much right direction & his use case falls in above 2 categories
Note :
The tipping decision to choose 1 from both will largely depend on how Massively, Badly, Largely, Mostly you be using two way data binding feature/setState.
As in react for two way data binding you have to write setState() , where as in angular you don't have such tension.
so if you have very less ui data computations like 2..3 per form than react is fine else straight away choose angular
Eg : suppose if you have 40 computations in local state like rate * quantity = amount so in react you have to write setState() for 40 times .so you miss 1 setState and final numbers will be wrong.So its better to use angular in this case
Eg : suppose if you have 40 computations in redux state .the it will be BULL**IT to write 40*50 extra coding lines.
For 1 computation
In angular you will write rate * quantity = amount total 1 line in angular.
But react Action 4 lines , Reducer 5 lines ,Component 3 lined total 12 lines in react.
Advice :
If you are not sure,then choose angular as it is having all extreme case features
Conclusion :
Its Not worth combining angular with react
Not sure about using both together but yes
You should play around with these together and see if you can improve your application.
Reactjs will help you to improve faster rendering but angular js 2.x will help you to improve Performance

ng-repeat - I'm confused on it works

I'm pretty new to angular js and I have a question about the ng-repeat. I'm following examples at AngularJs : https://docs.angularjs.org/guide/concepts
The section that I'm currently on is 'Adding UI logic: Controllers'. If you look at the index.html, specifically at the code:
<span ng-repeat="c in invoice.currencies">
{{invoice.total(c) | currency:c}}
</span>
When I run in the browser, everything works as expected, but I notice that invoice.total function runs at least 6 times. How do I know? Well in the index.js I added a console.log function within the total function as seen here:
this.total = function total(outCurr){
console.log(outCurr)
console.log(this.convertCurrency(this.qty * this.cost, this.inCurr, outCurr))
return this.convertCurrency(this.qty * this.cost, this.inCurr, outCurr);
};
I would expect the code to run 3 times because the invoice.currencies only has 3 items:
this.currencies = ['USD', 'EUR', 'CNY'];
However, this is what I see in my browser console window:
Any ideas? Thank you in advance?
user2341963 has probably the good answer so i'll quote it first and i'll add some precision.
The digest cycle runs at least twice to check that a value hasn't
changed. First time it runs for each of the values in this.currencies.
It runs again to check that the first digest cycle hasn't changed any
values. It hasn't so it stops after the 2nd cycle
In angular you have what we call a digest cycle. This cycle watch for any change that happened in the application bind to angular. In order to refresh it. This permit to refresh your DOM when you need without refreshing the whole page.
"The bind to angular" means
Every block between {{}}
Every use of scope.$watch or attrs.$observe which are used massively by directives (ng-model/ng-repeat/...).
I don't know what makes this cycle to trigger twice at start this is probably because of some internal mechanics or the filter that you use. Check this link for more info : https://www.ng-book.com/p/The-Digest-Loop-and-apply/

Need explanation on a angular direcive load

I just want to understand why in the following jsFiddle 'here is a lo' is printed three times.
http://jsfiddle.net/wg385a1h/5/
$scope.getLog = function () {
console.log('here is a log');
}
Can someone explain me why ? What should I change to have only one log "here is a log" (that's what I would like this fiddle do). Thanks a lot.
Angular uses digest cycles/iterations to determine when state has changed and needs to update the UI. If it finds any change on one of it's cycles, it keeps rerunning cycles until the data stabilizes itself. If it's done 10 cycles and the data is still changing, you'll see a rather know message: "angularjs 10 iterations reached. aborting".
Therefor, The fact that you are seeing the message displayed 3 times is because you have a simple interface. In fact, you can get up to many more such messages in the log, due to the fact that your directive uses {{getLog()}}. Angular keeps evaluating the expression to see if it changed.
To avoid such problems, under normal circumstances, you should store the value returned by the function you want called only once in the $scope object inside the controller and use that variable (not the function call) in the UI.
So in the controller you'd have $scope.log = getLog() [assuming it returns something, and not just writing to the console] and in the directive use the template {{log}}. This way, you'll get the value only once, per controller instance.
Hope I was clear enough.

Using Angular-Bacons $scope.$watchAsProperty(property) in Angulars ng-repeat

I´m trying to find a good way to use Baconjs together with Angularjs in conjuctions with Angular-Bacon.
Now digesting from Bacon to the Angular scope works perfectly fine but I´m stumbling with Angular-Bacons $scope.$watchAsProperty(property) within Angulars ng-repeat:
Let´s say I have the Angular scope $scope.databaserecords and render it out with:
<div ng-repeat="record in databaserecords">
Each of the records has a record.checked property and I want to handle all checked records together in one Bacon stream, for example to add a certain tag to all records at once.
At this point using $scope.$watchAsProperty(databaserecords) I get no Bacon events when checking or unchecking certain records, so how could I accomplish to receive these changes back in Bacon?
I might also mention, that using $scope.$watchAsProperty(property) out of ng-repeat, for example for input fields, works well without any problem.
Thanks for your help! :)
If I've understood correctly, your actual databaserecords remains the same throughout the scope, so you'll need to invoke $watchAsProperty with the objectEquality argument set to true:
$scope.$watchAsProperty("databaserecords", true)
By default angular opts to compare objects with a simple object equality check. In your case the list object remains the same, so a deeper check is necessary. This is already implemented in angular-bacon but it seems I've omitted it from the docs.

AngularJS jquery.flot chart directive DOM collision

i'm working with angular js now for about ke 4 months and despite all the "first step failures" like not emphasising the async way anuglar thinks, I'm facing a problem I don't really understand. It's not that easy to describe.
I have a provider which registrates directives within the routeprovider's resolve function - during config phase. To compile programmatically preconfigured directives I create them on the specific controller call of each route. Acutally the directive I'm adressing here is a complex flotchart directive. It retrieves data from a rest api, transformes the retrieved data and prepares different kinds of option setups like proper stacked line charts or simple piecharts. Every single step takes its time, so I introduced promises to be sure that everthing is at it's right place before I finally call something like "$.plot".
So now I have the following situation: Imagine a singlepage app with two tabs. Each tab - like a first class menu item - refers to a new page with a new controller to process and new partials to render. For each page i have beside other directives one of these heavy flotchart directives to render. actually it takes about 5 seconds to render the chart. So we assume that we really start the app from beginning - like pressing F5. Now I enter the first page the first time and within the mentioned 5 seconds I switch tabs to enter the next page. I get to the next page, see different partials, layouts and stuff and a loading chart - but actually the directive of the first page is still bound to its link phase of that heavy flotchart directive (still preparing options for flot and calculating data to output graphically).
My problem is that this link phase actually really ends within a completely different template/route/controller context and gets stuck. It crashes with a console "replace" error from jquery.flot. I think this error means that flot tries to plot into a div which does not exist anymore. But that error occures just when I switch tabs during the link phase of the first page's heavy flot directive. It doesn't happen when the first page's chart is fully rendered and doesn't happen when the first page's directive hasn't entered its link phase (or am i missing something??). I tried placing some console.logs directly BEFORE hitting the jquery "$.plot" - remember only of the first page chart directive to dive into what's acutally happening. And the strange thing is when I manage to switch tabs within these magic 5 seconds, I still get the console log entries from the first page entry although I'm on a different page. And now guess what. That's strange - acutally two directive link phases are running side by side and one of them on a completely different view (or isn't it completely different, because its a singel page app?). Imagine I plot ("render") the chart in exactly the same div id - like $('#flot-chart'). so I have html parts containing id="flot-chart" on the first page AND on the second. when I now switch from the first to the second page (not finishing the first chart) I get the chart from the first page rendered in the #flot-chart div of the second page and like half a second later the actually correct chart rendered in that same div. So actually the link phase of the first page's chart directive ends in a completely different page in a way showing 2 charts consecutively. I know jquery.flot depends on DOM manipulation via jquery and that might be the problem (perhaps THAT'S the only real explanation for my problem), because jquery DOM manipulation is out from the angular way of life.
Or are there other explanations? I acutally solved the problem via $routeChangeStart listening and killing the $.plot process, but are there some hints, suggestions, explanations for that behaviour?
Plunker flot chart directive DOM collision
I have prepared a plunker which shows kind of a similar behaviour. i've delayed the creation of the directive and the directive's async data and option retrieval methods to somehow mock the behaviour of my app. this is non production code but describes simplified the way my problems occure. when you "fast click" the menu item one after the other many times, you can sometimes force angular to show 2 charts in one page. acutally one directive is linking and doing stuff in a different partial ? i know i'm missing something in my mind ... please give me a hint.
i used chrome for reproducing the error. stop the the plunker and press 'run'. directly after pressing 'run' click as fast as you can both links a couple of times.
Thanks a lot!

Resources