I have a controller that receives a json list of items and repeats them in my view. I am using a variation of the bootstrap popover and would like to insert the order ID within the sub template defined my $scope.popover and have it parsed for variables. I read that the square brackets was the way to go but it does not seem to work for me.
function ManageOrderCtrl($scope, $http) {
$scope.subtemplate = '<input class="hidden" value="[order._id]">';
$http.get('/api/orders').
success(function(data, status, headers, config) {
$scope.orders = data.orders;
});
};
}
Template (is actually a directive - a variation of the bootstrap popover):
<li ng-repeat="order in orders">
{{ order._id }}
<li>
You can try something like
<li ng-repeat="order in orders">
{{ order._id }}
<li>
Instead of defining the template in controller. You can also create templates using ngInclude and include them in the html.
Related
I'm using an angular directive and I am not having any luck with the jQlite .find() method:
DIRECTIVE
function cardsList () {
return {
restrict: 'A',
controller: 'CardsController',
templateUrl: 'app/directives/cards-list/cards-list.html',
link: function ($scope, $element, attr, CardsController) {
var cardLink = $element.find('a');
console.log(cardLink);
});
}
}
}
contextCards.directive('cardsList', cardsList);
An empty [] gets logged on the console.
TEMPLATE
<li data-ng-repeat="card in cards" class="cards--item">
<a class="cards--link" data-ng-href="#/{{ card.slug }}">{{ card.title }}</a>
</li>
VIEW
<ul class="col-xs-12 cards--list" cards-list></ul>
All I want to do is traverse to the <a> elements. According to the docs, .find() only works on tag names which is exactly what I'm trying to do.
EDIT: I want to add a class to the <a></a> if the card the link represents is selected (like .current-card)
From your answer it's not clear how the selected card is specified in the model, so I am assuming that the card object (the object of each iteration of ng-repeat) holds this flag, for example: card.isSelected.
Then, you could use ng-class to specify which CSS class to add based on this value:
<li ng-repeat="card in cards" class="cards--item">
<a class="cards--link"
ng-class="{'current-card': card.isSelected}"
ng-href="#/{{ card.slug }}">{{ card.title }}</a>
</li>
Addendum:
The answer to your original question about why .find("a") returns empty, it is because ngRepeat directive transcludes its content (which means that Angular takes the elements out of DOM during compilation), and places it at a later stage than your link function.
I'm trying to implement a feature using Angular and Boostrap where the user can get a popOver on an item in the list, and have it perform an angular factory $http.get function to retrieve data and populate the popover text.
I'm not sure this is the best approach, but I have a ng-repeat like so:
<ul>
<li ng-repeat="product in products">
<model-popover ng-attr-id="{{product.Id}}"></model-popover>
</li>
</ul>
And my best guess is to use an angular directive, taking in the id number as a scope attribute,and performing a factory call from the directive. I've read up on the controller/link functions within the directive, but not sure the proper implementation
app.directive('modelPopover', ['Factory', function (Factory) {
return {
restrict: 'E',
replace: true,
scope: { id: "=" },
controller: function($scope){
var prod = Factory.getProductDetail(id);
},
template: '<a popover-placement="bottom" popover="{{prod}}">{{prod}}</a> '
};
}]);
I know the directive is incorrect, but i'm hoping there's enough information to help me out. Thanks in advance!
You do not need special directive for this, due to value-binding u can just change scope variable and popover will change also.
So u simply:
<button popover="{{var}}" popover-trigger="mouseenter" class="btn btn-default" ng-mouseover="changeVar()">Mouseenter</button>
And in changeVar you can change $scope.var any way you want.
Here is example plunk ($http call emulated using $timeout):
http://plnkr.co/edit/gnm1BtnHzNLnvO62Ar2i?p=preview
This var prod = Factory.getProductDetail(id);
has to be changed to $scope.prod = Factory.getProductDetail(id) if you want to use the mustaches
Good morning,
I'm trying to change the limitTo filter on a certain list, my issue is:
when I click to the trigger who change the filter limit the filter changes on all ng-repeated categories.
my function inside the main controller
$scope.showMore = function(limit) {
if($scope.limitItems === $scope.itemsPerList) {
$scope.limitItems = limit;
$scope.switchFilterText = 'less';
} else {
$scope.switchFilterText = 'more';
$scope.limitItems = $scope.itemsPerList;
}
}
my scenario (I rewrote it in a simplified version)
<li ng-repeat="item in category.items | limitTo: limitItems ">
{{item.title}}
</li>
<li ng-if="limitItems < (category.items.length)">
<a ng-click="showMore(category.items.length)" >Show {{ switchFilterText }}</a>
</li>
Could you explain me what's wrong with me?
I searched how to select a single element to apply the function but I didn't find anything useful
Update:
I found the way to solve my issue in this way:
No functions inside the controller are involved to make this functionality works properly:
<li ng-repeat="category in maincategories" ng-init="limitItems = maxItemsPerList">
{{category.title}}
<ul>
<li ng-repeat="item in category.items | limitTo: limitItems "> {{item.title}}
</li>
</ul>
<a ng-click="limitItems = category.items.length" href>
<b ng-if="category.items.length > maxItemsPerList && limitItems != category.items.length "> Show more </b>
</a>
I'm not really convinced about Angular (I used it in my past and I was impressed by the performance but now I can see logics senseless):
What I learned:
ng-if and ng-click cannot be used in the same content because ng-if creates new scopes so if you put ng-if on top of the "show more" link it will break the code
ng-init cannot be used in the same element of the ng-repeat otherwise the var initialised will not be available inside the ng-repeat block
I think there is another way to do that, maybe more clean but in this specific case I can't do a lot.
ng-if and ng-click cannot be used in the same content because ng-if
creates new scopes so if you put ng-if on top of the "show more" link
it will break the code
Yes, ng-if creates a new scope, but it is possible to mix ng-if and ng-click (and most other directives). To do that, you'll be safer if you always write to atributes of another object instead of a simple variable. It is plain JavaScript prototypal inheritance in play.
<li ... ng-init="category.limitItems = maxItemsPerList">
ng-init cannot be used in the same element of the ng-repeat otherwise
the var initialised will not be available inside the ng-repeat block
True, in the sense that variables are created in the local scope. But again, refer to an object.
I think there is another way to do that, maybe more clean but in this
specific case I can't do a lot.
You don't need to do a lot, it is quite simple to do it right actually.
Some advices:
Use ng-init with care. I know it will tempt us but always try to put logic inside controllers and services;
Avoid assignments inside templates;
Learn how to use controllerAs syntax. It gives you an object to write your models to (the controller), so solves most problems related to scope inheritance;
Do not inject $scope, put your view models inside controllers.
Full code goes like this:
<li ng-repeat="category in maincategories" ng-init="category.limitItems = maxItemsPerList">
{{category.title}}
<ul>
<li ng-repeat="item in category.items | limitTo: category.limitItems "> {{item.title}}
</li>
</ul>
<a ng-if="category.items.length > maxItemsPerList && category.limitItems != category.items.length" ng-click="category.limitItems = category.items.length" href>
<b> Show more </b>
</a>
<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>
Here is my json data
[{"Country" : "Germ<sup>any</sup>"},{"Country" : "Swe<sup>den</sup>"}]
Here is how i am fetching it using angular js
<div ng-app="" ng-controller="customersController">
<ul><li ng-repeat="x in names">{{ x.Country }}</li></ul>
</div>
and the controller script
function customersController($scope,$http){
$http.get("http://localhost/sample.php").success(function(response) {$scope.names = response;});
}
The output i am getting is
<ul>
<li>Germ<sup>any</sup></li>
<li>Sweden</li>
</ul>
But the output i wanted is
<ul>
<li>Germ<sup>any</sup></li>
<li>Swe<sup>den</sup></li>
</ul>
Need help to sort this out...
You need to use ng-bind-html for the div you are trying to print HTML content.
Refer to this link for details and change the code accordingly.
By default, AngularJS sanitises your data and strips all HTML.
To achieve what you desire, use the $sce service to mark the data as trusted and the ngBindHtml directive to bind it to the view, like this:
Add a new filter
app.filter('unsafe', ['$sce', function($sce) {
return function(text) {
return $sce.trustAsHtml(text);
};
}])
Use it in HTML
<ANY ng-bind-html="data | unsafe"></ANY>