AngularJS if statement with ng-repeat - javascript

I'm having trouble trying to use an if alongside a repeat statement.
I'm fetching data, as follows:
modules: Array[1]
0: Object
embed: "<iframe width="600" height="338" src="https://www.youtube.com/embed/UqdDAn4_iY0"
frameborder="0" allowfullscreen="" style="margin:0px auto;display:block;"></iframe>"
type: "embed"
1: Object
src: "https://m1.behance.net/rendition/modules/127899607/disp/072cebf2137c78359d66922ef9b96adb.jpg"
type: "image"
So, if the module has a type of image, i want to get the image. If it has type embed, i want to get the iframe. My current view code is:
<div ng-repeat="project in project.modules" ng-if="project.type == 'image'">
<img src="{{ project.src }}" class="img-responsive img-centered" alt="{{ project.name }}"/>
</div>
It works well if i take out ng-if. Console outputs the following error:
Error: Multiple directives [ngRepeat, ngIf] asking for transclusion on: <!-- ngRepeat: project in project.modules -->

You can use filter instead of using ngIf. Your code shall be like:
<div ng-repeat="project in project.modules | filter: { type: 'image' }">
And it shall work.
The solution you're trying to do in your code can't be done as ngIf and ngRepeat both trying to remove and replace some elements and do some transclusion.
Check this issue https://github.com/angular/angular.js/issues/4398
Also check the usage of filters https://docs.angularjs.org/tutorial/step_09
and this question shall be useful with using ngRepeat with filters ng-repeat :filter by single field

This is because you have to do the if condition inside the ng-repeat block. For example:
<label ng-repeat="elem in list">
<div ng-if="...">
show something for this condition
</div>
</label>
Why do you need the ng-if to be alongside the ng-repeat?

this should display only "article" and "article1" on screen
<li ng-repeat="value in values" ng-if="value.name == 'article' || value.name == 'article1'">
<label>{{value.name}}</label>

You can't use ng-repeat and ng-if on the same element, because both of them want to do things like remove & replace the entire element. This kind of makes sense - what would you do when ng-repeat is saying "hey draw this" but ng-if is saying "hey no don't draw this?"
I think the best solution here would be to preprocess your array to only include the records you want, and then ng-repeat over that with no ng-if. You could also move the ng-if to an element inside the ng-repeat element, so that there is no ambiguity about what's shown & hidden.

Related

ng-bind-html doesn't connect different things in once (not even with $sce.trustAsHtml() )

I am trying to connect some different html code to my view with ng-bind-html.
I already added ngSanitize
Firstly I am using ng-for by ui-select-choices
<ui-select-choices repeat="test in dataTest>
. and I want to bind test.name with some Html
<small> ( {{ TEST_BTN | translate }}) </small>
The Test_BTN is being used for Translation purpose there fore I can't leave it out from code.
when I try to use them all in ng-bind-html nothing will be shown
when I try to use them all in ng-bind the html code will be shown.
when I try to use ng-bind andng-bind-html seperetly , ng-bind-html html won't be shown.
How am I suppose to fix this?
EDIT : I am trying to show the result in a new div with ng-if
something like : <div data-ng-if="test.isSomething" ng-bind="test.name" ng-bind-html="' <small>({{'BTN_ADD' | translate}})</small>'" ></div> (Which doesnt show the ng-bind-html part )
EDIT 2 :
I deleted the {{ }} from data-ng-bind-html and used the translation explicitly with the $translate service in my controller.
And It worked.
You can't use ng-bind and ng-bind-html on the same element, and you can't use {{}} in either one of them. It's not necessary to concatenate the <small> tag inside the ng-bind-html, it should be in the template itself. And you have some syntax error nested-quotes issues in your ng-bind-html clause.
It's not clear to me from your description which of test.name, TEST_BTN or BTN_ADD you actually intend to use; I'm going to assume you really want test.name here but if one of those other variables contains the HTML you're trying to embed, just substitute its name in place of test.name:
<div ng-if="test.isSomething">
<small ng-bind-html="test.name | translate"></small>
</div>

Angular 1.4: How do I force update of directive within a ng-repeat with filter?

How does one force a directive to update if it nested in a ng-repeat which has a filter?
Input Box
<input type="text" class="name-search" ng-model="search.text">
HTML
<ul>
<li ng-repeat="user in users track by $index | filter:search">
<profile-photo user="user"></profile-photo>
<span>{{ user.name }}</span>
<li>
</ul>
As I type in the input box, the users filter properly but the profile-photo directive doesnt have the proper user.
Any help would be greatly appreciated!
Heres a dumbed down Plunker of my actual code. If you start typing, you will notice that it filters but the image doesnt update.
https://plnkr.co/edit/FWD2bFdIh7jQa5aqdkjrPlunker
your link's function code only executes once, when compiling the directive. After that, scope.photoUrl does not change even if you change the user, because you're not $watching the value. You can add a watch, or directly, use this in the template
ng-src="{{user.photoUrl}}"

ng-non-bindable with ng-if in Angular Google Maps

So I read Why is ng-non-bindable required for <ui-gmap-windows> element in Angular Google Maps?
and I get how ng-non-bindable is used in the directive.
My problem is that I'm trying to use ng-if to conditionally reveal some icons in my marker infowindows. ng-if doesn't work with ng-non-bindable, and of course, the info windows don't work without it.
If someone can tell me how to make ng-if work in this situation or give an alternative solution, i'd greatly appreciate it.
<ui-gmap-windows show="show">
<div ng-non-bindable>{{obj.name}}<br>{{distance}} miles
<span class="ion-man" ng-if="obj.men"></span>
<span class="ion-woman" ng-if="obj.women"></span>
<span class="ion-ios-people" ng-if="obj.people"></span>
</div>
</div>
</ui-gmap-windows>
You need to use the templateUrl and templateParameter attributes on the ui-gmap-windows directive. The templateUrl is a property on the object that you're passing in which is a string that is the path to the .html template you want to use. The templateParameter is a property on the object that you are passing which is an object containing the parameters you want passed in. See code below. Also you can reference the docs here: http://angular-ui.github.io/angular-google-maps/#!/api/windows
<ui-gmap-windows idKey="'name'" show="show" templateUrl="'pathToHtmltemplate.html'" templateParameter="'{name: 'name', distance: 1.3, womens_restroom: true}'">
</ui-gmap-windows>
Then in your html template you can use ng-if no problem.
Note you have to reference the object you pass into templateParameter as parameter in the html template so the
pathToHtmlTemplate.html file would look like this
<div>
{{parameter.name}}<br>{{parameter.distance}} miles
<span ng-if="parameter.womens_restroom" class="ion-woman"></span>
</div>
The reason it does not work is because, ng-if (600) has lower priority than ng-non-bindable (1000) and ng-non-bindable is terminal:true so ng-if never compiles due to the terminal nature of ng-non-bindable. You could try using ng-switch (1200) directly on the element with ng-non-bindable though since it has higher priority but not sure if that is applicable in your case if you may have multiple conditions that can be true.
You can as well create your own directive say my-non-bindable anddefine it with configuration, {priority:599, terminal:true} and use it with ng-if say:
.directive('gmapTemplate', function() {
return {
priority: 599,
terminal: true
};
});
and use it with ng-if.
<div gmap-template ng-if="someCond">{{obj.name}}<br>{{distance}} miles
Otherwise you will have to wrap non bindables within element with ng-if
<div ng-if="someCond">
<span ng-non-bindable>{{obj.name}}<br>{{distance}} miles</span>
</div>
angular.module('app', []).directive('gmapNonBindable', function() {
return {
priority: 599,
terminal: true
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<div ng-app="app" ng-init="test:123; show:false">
Show-->
<input type="checkbox" ng-model="show" />
<div gmap-Non-Bindable ng-if="show">{{test}}</div>
</div>

ng-repeat="(key, value)" cannot use value of {{key}} as part of global scope for another directive

<div ng-repeat="(key,x) in selectedPoll.questions">
<p>{{x}}</p>
<p>{{key}}</p>
<canvas chart-directive data="arrayResult.{{key}}" id="{{ $index }}">
</canvas>
</div>
When i use {{key}} in global scope for chart-directive, {{ $index}} is not accessible, although when i delete {{key}} and leave just arrayResult, ng-repeat is working.
Explanation: i use id {{ $index }} which is searched by chart-directive for each x in ng-repeat, thanks to this i can create as many chart-directives as i need.
Then in order to everything work properly i have to pass proper dataset, each dataset for chart-directive has the same ending as {{ key }} of x in ng-repeat so for example:
data="arrayResult.q1 "
to make it dynamic i would like to switch it to:
data="arrayResult.{{ key }}
but when i add {{ key }} ng-repeat stop with one result which as i assume is happening because it cannot read id value of {{ $index }}
It is the first time i use key and $index with ng-repeat, and it is first time when i repeat custom directive, so i don't know if the problem is with repeating custom directives or rather wrong use of {{ key }} value.
Just when i added the question some solution came to my head, it could be that it is happening because in my custom directive my scope.data looks like this
scope: {
data:'='
},
So If I am right if somebody can tell me if it is possible and if it is how to make scope data open for expression like this "arrayResult.{{ key }} ??
Using # is only relevant if your chart data are strings.
You can keep the = of your directive, but you need to change:
data="arrayResult.{{key}}"
into this:
data="arrayResult[key]"
The curcly brackets will only work with a # scoping indeed, but you would get the string "arrayResult.q1" instead of the actual value of what is in arrayResult.q1, so = is the way to go.
See a snippet simulating it below:
angular.module("test", []).controller("test", function($scope) {
$scope.questions = {q1: "do you like apples?", q2: "do you like bananas?"};
$scope.arrayResult = {q1: true, q2: false};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test" ng-controller="test">
<div ng-repeat="(key,x) in questions">
<p>question: {{x}}</p>
<p>key: {{key}}</p>
<div>result: {{arrayResult[key]}}</div>
</canvas>
</div>
</div>

How can I pass a variable into an ng-include?

I have the following code:
<div ng-repeat="item in items">
<div ng-include src="itemG.html"></div>
</div>
then in itemG.html I have:
<img src="{{item.image}}">
How can I get my ng-repeat to print out all of the images?
There are 2 potential problems in the code...
src="itemG.html" needs an extra pair of single quotes like this:
<div ng-repeat="item in items">
<div ng-include="'itemG.html'"></div>
</div>
And the img tag is missing a closing ":
<img ng-src="{{item.image}}">
Plunker: http://plnkr.co/edit/7IUs7WPdUYkfVVKtBN1m?p=preview
Basically, what this comes down to is that the browser will interpret what inside the src attribute literally, until angular comes along to replace it. If you have a string constant, you can use single quotes inside the src="'myurl.html'", but if you have a value that needs to be bound by angular, you have to use ng-src and the expression syntax of {{ }}
You also need to bind a model to your template file itself. It's not going to pick up the bindings from your repeater without some help from either the ng-include event directives, or it's own model/controller/directive. There are too many different ways to demonstrate that, and it's also relevant on what markup is in your template file, which I can't say.
However, if the img tag is the only thing in that file, then instead of the file, I'd just do this:
<div ng-repeat="item in items">
<img ng-src="item.image" />
</div>
Since you're inside a repeat, it's already being included, making the ng-include redundant.
In principal code
<div ng-repeat="item in items">
<ng-include src="itemG.html" ng-controller="MyCtrl" ng-init="i=item"><ng-include>
</div>
then in itemG.html I have:
<img src="{{i.image}}">

Categories

Resources