Here is an example of a select that has an option added every second.
For some reason, the options don't appear every second but seemingly randomly. However, if you continually move your mouse the options DO appear every second. Seems like an event needs to be fired?
If you remove select size, it works.
See demo
Alternatively, you can render something using state, which will cause the options to appear each second.
<div style={{ height: 0 }}>{this.state.parts.length}</div>
//hack
I am still looking into exact reason of why it is happening but above options will make your options appear as per your expectation.
Related
Ok, I know that title could use some work, but I'm not sure how else to put it.
Here's the setup.
I have a (potentially) massive table that gets generated via an ng-repeat. All the rows need to be editable but, when the dataset is so large, all those bindings slow things to a crawl. I could literally be waiting upwards of 20 seconds for large sets to load!
We noticed that dumping the data in a read-only state significantly decreased the load time. So, we came up with the idea of loading it read-only, but, when the table row was clicked, it became editable. This is accomplished like so. I have two cells output. editableRow is initially false. When the row is clicked, editableRow becomes true. The idea being that, when editableRow becomes true, I see the other cell.
(proprietary code obfuscated)
<TABLE-CELL class="value-col" ng-if="readtime.editableRow === true">
<input type="text"
name="readingTime"
ng-model="<data model>"
ng-disabled="<param>"
ng-change="<function>"
ng-class="<classes>"
/>
</TABLE-CELL>
<TABLE-CELL class="value-col" ng-if="readtime.editableRow === false">
<input type="text"
placeholder="{{<data model>}}"
ng-class="<classes>"
/>
</TABLE-CELL>
The problem is, on the click, for a tiny fraction of a second both cells are visible. It really is only visible on the first click. Subsequent clicks still do it, but it goes so fast that the human eye can't catch it. I know it's there since I slowed everything down with a breakpoint on the mouse click. This also revealed that this happens as the value turns true - turning on the first cell, but the second one doesn't disappear in the same moment. So, it causes a "flicker" of sorts. This seems to happen outside my actual code, inside the jQuery, so I'm not sure how to short circuit it.
I've tried playing with using ng-show/hide instead, which worked a little bit, but also totally negated the time-saving aspect, since it actually renders everything, and it took a long time. I've also tried ng-cloak with no effect whatsoever.
The breakpoint that it keeps stopping on (when I told it to stop on event listeners to do with the mouse click) is the following code in jquery.js:
if ( !(eventHandle = elemData.handle) ) {
eventHandle = elemData.handle = function( e ) {
// Discard the second event of a jQuery.event.trigger() and
// when an event is called after a page has unloaded
return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
jQuery.event.dispatch.apply( elem, arguments ) : undefined;
};
}
It hits that line about 4 times, and, on the last one, both cells are visible. Then, the second one disappears.
I'm out of ideas and would appreciate any thoughts on this.
I finally found an answer that works!
On this page: disable nganimate for some elements the answer right BELOW the accepted answer is what finally worked!
To disable ng-animate for certain elements, using a CSS class, which follows Angular animate paradigm, you can configure ng-animate to test the class using regex.
Config
var myApp = angular.module("MyApp", ["ngAnimate"]);
myApp.config(function($animateProvider) {
$animateProvider.classNameFilter(/^(?:(?!ng-animate-disabled).)*$/);
})
Usage
Simply add the ng-animate-disabled class to any elements you want to be ignored by ng-animate.
I have a number of Div's on a layout, each of them draggable, so there's the possibility of the user dragging them into positions where they will overlap.
I want to set the most recently made visible div to have a z-index value that's +1 from the last, and for this I'm using a $scope.nextIndex variable that's incremented each time one of the div's is made visible.
Each div has its own variable to track its own z-index value: $scope.one_zIndex, $scope.two_zIndex, $scope.three_zIndex, and each correctly gets assigned an incrementally larger value as each div is shown, hidden and shown again.
Each div has its own class: one_z, two_z, three_z
What I can't make work is assigning the variable to the z-index style on the divs themselves via the controller.
var myVar = document.getElementsByClassName("one_z");
If I log this to the console, I get what I expect - an array with one element [0]
[]
0 : div#one_z
length : 1
one_z : div#one_z
__proto__ : HTMLCollection
I would assume that I could set the z-index simply like this:
myVar[0].style.zIndex = $scope.one_zIndex;
However this throws an error:
Uncaught TypeError: Cannot set property 'zIndex' of undefined
What am I missing? Or is there a better way to accomplish this?
Here is a working plunker https://plnkr.co/edit/aaDipIWdqpajghc2F2Da?p=preview
You can set zindex via ng-style:
<div ng-style="{'z-index': $lastIndex;}">...</div>
This example completely useless in your case, but there is an example of ng-style usage. In your case I'd set index as property of you div element data source.
What wound up working was this:
First, I switched to IDs instead of classes, which likely didn't impact the solution but as each div was only ever going to exist once, IDs was the more correct way of identifying them.
Then, in the function that displays the div, I used this:
_.defer(function(){
jQuery('#one_z').css('z-index', $scope.one_zIndex);
});
There appeared to be an issue where I was showing the div and trying to set its z-index before the DOM had updated to include the div, so _.defer (I'm using Underscore.js) prevented the accessing of the z-index until everything had updated once, and it works.
As I mentioned in another comment - using ng-style wasn't working for me, and I had tried the _.defer with that approach as well initially without success.
For the record - I've used jQuery() instead of $() so it's clear in the code that this is a jQuery and not an Angular solution, and while I'd ideally have liked a purely Angular solution to this problem, this is clean enough for me, and doesn't do any DOM manipulation outside of Angular's purview that impacts the rest of the application in any way, it's purely display candy.
Basically, what my client asked me to do is similar to tag friends in Facebook/youtube comment.
must start with #
a popup suggesting a list, upon selected, the value is appended back to the original contenteditable
I have tried
https://angular-ui.github.io/bootstrap/
and ngTagsInput , they are close but not enough... thanks
I bet this is what you are looking for http://angular-ui.github.io/ui-mention/example/ . I have to admit it took me quite a few days to find it (via google)
Good luck
You're building autocomplete for tags. If you plan to reuse it, then you'll need to write a custom directive. If not, then you can do a messy implementation inside of your controller.
You'll need the html element you are editing to look like this:
<div ng-model="newtag" ng-change="tagchanged()" ng-bind="newtag"></div>
ng-change will fire on change, so your function will need to have a debounce (wait a period of time) in order to wait until the user finishes typing. You can accomplish this with a setTimeout of 500ms. If it changes during that time period, kill the timeout. But if it doesnt, do your api call to get the list of potential tags and show them in a list below the field. You'll want the css for the results to let them align to the search field and hover above the rest of your page.
I had a bit of code in my view that would only show up when a particular value was true. Lt looked like this:
button type="button" ng-click="attachBarCode('enter')" ng-show="barcodeAllowed.status">Foo</button>
This was working until recently. My controller had some logic where, based on Ajax data, it would set $scope.barcodeAllowed.status to true. All of a sudden though, the button was always showing up. To help debug the issue, I added some additional tests to my view:
first test, <span ng-show="!barcodeAllowed.status">DONT SHOW</span><br/>
second test, <span ng-show="barcodeAllowed.status">DONT SHOW</span><br/>
test -{{barcodeAllowed.status}}-end -{{!barcodeAllowed.status}}- -{{barcodeAllowed | json}}-<br/>
test if <span ng-if="barcodeAllowed.status"> if was true</span><p>
Here is where things got crazy. Both "DONT SHOWS" rendered in my view, even though it seems as if that would be impossible. When I output the values in the third line, I saw false and true, as I expected.
Finally - the ng-if? It worked perfectly! The value did not show up.
I've heard folks mention that ngShow can have scope issues inside a ngif, but my code isn't inside an ngif.
So, you won't believe what it was. I was using a Content Security policy in my app and on a whim, I disabled it. As soon as I did, it began working. I played around a bit and discovered that I needed to add 'unsafe-eval' to the to the script-src area of my CSP in order for Angular to be able to apply the styles.
The Ng-show/Ng-hide directives needs a css-class to show/hide, since it just adds a class to your element when the scope-variable is truthy/falsy.
Ref: https://docs.angularjs.org/api/ng/directive/ngShow
So, I have made some custom directive which draws kind of a data-grid, based on floated divs (because nested flex implementation in FF sucks - but it's not the point).
How it works :
I pass some data collection to the directive via something like <the-grid data-list="parentController.displayedRows">
Inside this first directive, I have columns via something like <a-grid-column data-value="row.value"></a-grid-column> with many attributes I won't precise here.
The data-value value can be a direct expression, bound to the row on which the the-grid directive controller is ng-repeating in order to display each columns, or a function which have to be $eval-uated in order to display the intended value from the parentController.
In my <the-grid> directive controller, I have the rendering template of my grid which make a nested ng-repeat div (first one on the rows of the data-collection, second one on the columns, created in the directive), it looks like :
<div data-ng-repeat="row in list">
<div data-ng-repeat="cell in theGridColumns"
data-ng-bind-html="renderCell(row, cell)">
</div>
</div>
I have some keyboard nav in order to quickly select a row or navigate within pagination or many tabs, which does nothing more than applying some class on the selected row, in addition to update some "selectedRowIndex".
I'm using angular-vs-repeat in order to have the minimum of row divs in my DOM (because the app is running on slow computers). This works well.
The problem is that every time I'm hitting some "up" or "down" key on my keyboard, Angular is "redrawing" EVERY cells of the list.
So, let's suppose I've 200 rows in my data list, and 7 columns for each rows. First load of the page, it passes ~3000 times in the renderCell() function. Ok , let's accept that (don't really understand why, but ok).
I hit the down key in order to go to the second line of my list. It passes ~1100 times in the renderCell() function.
So yes, the result is very slow (imagine if I let the down arrow key pressed in order to quick navigate within my rows)... I can't accept that. If someone could explain that to me... Any help would be greatly accepted :)
If I make the same thing without a directive (direct DOM manipulation, with columns made by hand and not in a ng-repeat within a ng-repeat), every thing is smooth and clean.
Yes, I've look into every angular grid on the market. No one is satisfying me for my purpose, that's why I've decided to create my own one.
And no, I really can't give you some JSFiddle or anything for the moment. The whole app is really tentacular, isolating this is some kind of complicated).
Try to use bind once (angular 1.3+)
<div data-ng-repeat="row in ::list">
<div data-ng-repeat="cell in ::theGridColumns"
data-ng-bind-html="::(renderCell(row, cell))">
</div>
</div>