Angular show-hide flickers - angularjs

I'm switching the visibility of 2 elements when clicking them. A very simple use case:
<div ng-hide="filtersOpened"
ng-click="filtersOpened=true">
filters (opened)
</div>
<div ng-show="filtersOpened"
ng-click="filtersOpened=false">
filters (closed)
</div>
The change happens, but it flickers so that for a very short moment I see both elements together.
How can I make the change behave nicer, smoother, without the flickering? I've read about ng-cloack but doesn't seem like it's related since I'm not using a template.

Maybe try ng-if instead:
<div ng-if="filtersOpened" ng-click="filtersOpened=true">
filters (opened)
</div>
<div ng-if="!filtersOpened" ng-click="filtersOpened=false">
filters (closed)
</div>

Related

Expanding tiles layout using Angular in responsive layout

I'm developing an Angular single-page app with a responsive layout. The current page I'm working on uses a tile-based layout that auto wraps extra tiles to the next row. The HTML is below and, in the responsive layout, it can show 1, 2, or 3 tiles per row depending on the width of the row (it positions them using floats).
<div class="tiled_panel">
<div class="tile_1">...</div>
<div class="tile_2">...</div>
<div class="tile_3">...</div>
<div class="tile_4">...</div>
<div class="tile_5">...</div>
...
</div>
Now each tile will be given a "Learn More" button. The design calls for a block to expand between the row of the selected tile and the row below. This block will be the full width of the row and will be closed when the user closes it or clicks on a different Learn More button.
My first thought was to arrange the HTML as below using ng-if to hide or display the expander divs but I can't figure out the CSS needed to have it display between the rows.
<div class="tiled_panel">
<div class="tile_1">...</div>
<div class="expander_1">...</div>
<div class="tile_2">...</div>
<div class="expander_2">...</div>
<div class="tile_3">...</div>
<div class="expander_3">...</div>
<div class="tile_4">...</div>
<div class="expander_4">...</div>
<div class="tile_5">...</div>
<div class="expander_5">...</div>
...
</div>
My second thought, since I'm using Angular, was to somehow use transcluding or including to insert the relevant HTML into the appropriate spot. Again, I can't figure out how to identify where I need to insert the HTML?
I've tried searching around for other people's solutions to similar problems since I figured its not that unusual a requirement but I haven't yet been able to find anyone else who is doing this.
Can anyone else suggest what I need to do to identify the where to insert the HTML or how to generate the CSS? Or even suggest another solution that I haven't considered yet?
Although I have 70% understand of what you mean, I think ng-class can simply solve what you've faced. The solution code is like below. And I setup jsfiddle.
Html looks like this.
<div ng-app="" ng-controller="MyCtrl">
<div class="tiled_panel">
<div>Tile 1 <a href ng-click="change_tile(1)">More</a></div>
<div class="expander" ng-class="{'close': opentile===1}">Expander 1<a href ng-click="change_tile(-1)">Close</a></div>
<div>Tile 2 <a href ng-click="change_tile(2)">More</a></div>
<div class="expander" ng-class="{'close': opentile===2}">Expander 2<a href ng-click="change_tile(-2)">Close</a></div>
</div>
</div>
Your controller code looks like this.
$scope.change_tile = function(value){
$scope.opentile = value;
}
$scope.change_tile(0);
Css looks like this.
.expander{
visibility: hidden
}
.close{
visibility: visible
}

Replace ui-view with the loaded content

I have multiple views like here : http://www.funnyant.com/angularjs-ui-router/
And I load them in my page like this
<div data-ui-view="content"></div> --- 75% width
<div data-ui-view="sidebar"></div> --- 25% width
Now, when the content is loaded, I want the loaded content not load inside these ui-view divs, but to replace them. Is it possible ? because if they don't replace then in my situation the float won't work and the sidebar shows bellow the content.
Help please
thanks
Using Bootstrap rows would this achieve your aim?
<div class="row">
<div class="col-md-9" ui-view="content"></div>
<div class="col-md-3" ui-view="sidebar"></div>
</div>
This is not possible and would be undesirable as it would leave you unable to change states. A simple workaround would be to add the width/float styles directly to the ui-view divs.
If you are determined to make it work you could create a custom directive wrapper like the solution provided here.
Try adding your desired sizes to the style of the containers.
<div data-ui-view="content" style="width: 75%;"></div>
<div data-ui-view="sidebar" style="width: 25%;"></div>

Using ng-repeat to created a nested dom structure

Is it possible to use ng-repeat (given the data source below) to create the following DOM structure?
JS
scope.data = ['a', 'b', 'c', 'd']; // The size of this array varies
HTML output
<div class="a">
<div class="b">
<div class="c">
<div class="d">
</div>
</div>
</div>
</div>
I don't want to change the data source, and I have also tried playing ng-repeat-start and ng-repeat-end to no avail. I was thinking that perhaps I could use multiple ng-repeat instances (one to create the opening tag and the other to create the closing tag) but am not sure how I could implement this.
Would I need to write a custom directive for this?
UPDATE
The solution described by sylwester only works if you know the size of the data array, however I am interested in a solution that renders the required divs based on a indeterminate array length.
Please see here :http://jsbin.com/tijiq/1/ is working but not recommended as very easy to lost yourself.
<div class="{{data[0]}}">
<div class="{{data[1]}}">
<div class="{{data[2]}}">
<div class="{{data[3]}}">
hello
</div>
</div>
</div>
</div>

angularjs - toggle ng-class from multiple ng-clicks

I've just started working on a project that requires me to learn AngularJS. What I'm trying to do is create two menus that slide into the screen, one from the left, one from the right. When they do this they push the content over.
Currently I can get one or the other to work, but not both. I realize this is because of the way that I'm defining the ng-class. I just can't quite conceptualize how to do it correctly.
<div ng-class="{true:'slide-left', false:''}[toggleSlide]" class="container">
<div class="content">
<button ng-click="toggleSlide = !toggleSlide" class="btn-left">From Left</button>
<button ng-click="toggleSlide = !toggleSlide" class="btn-right">From Right</button>
</div>
<div class="slide-from-left">
<p>Here is information that slides from off screen left.</p>
</div>
<div class="slide-from-right">
<p>Here is information that slides from off screen right.</p>
</div>
</div>
Set up the ng-class syntax like this for what you want:
<div ng-class="{'slide-left':toggleSlide, 'slide-right':!toggleSlide}" class="container">
Also, I'm guessing you were trying to adapt your code to something else you saw, so I'll offer something on that also. Here's an ng-class using ng-repeat's $index to dole out classes for even and odd:
ng-class="['even', 'odd'][$index % 2]"

How to write a directive which can render some html code with angular directives, and show it as text?

I think some sample code can explain my purpose.
Some html code with angular:
<div ng-init="buttons=['add','edit','delete']">
<div show-result-as-text>
<button ng-repeat="button in buttons">{{button}}</button>
</div>
</div>
You can see there is a custom directive "show-result-as-text" which I want to define. It should render the inner html code with angular directives, then show them as text.
The final html should be:
<div ng-init="buttons=['add','edit','delete']">
<div show-result-as-text>
<button>add</button>
<button>edit</button>
<button>delete</button>
</div>
</div>
And when the buttons value changes, the escaped html should also be changed.
I've tried to write one myself, but failed after 2 hours of work.
UPDATE
A live demo: http://plnkr.co/edit/fpqeTJefd6ZwVFEbB1cw
The closest thing I could think of is exemplified here: http://jsfiddle.net/bmleite/5tRzM/
Basically it consists in hiding the src element and append a new element that will contain the outerHTML of each src child.
Note: I don't like the solution but it works, so I decided to share it...

Resources