How to find minimum value in ng-repeat? - angularjs

Hi i'm trying to get the minimum price in my repeater. I'll add a green sign near to this list item. (as you see in code, "span class min-value")
How can I get this minimum value and use my span as "ng-show" in my html?
Thank you.
var app = angular.module("App", []);
app.controller("Controller", function($scope) {
$scope.priceList = [{
"name": "Product 1",
"price": "100"
}, {
"name": "Product 2",
"price": "200"
}, {
"name": "Product 3",
"price": "300"
}, {
"name": "Product 4",
"price": "400"
}, {
"name": "Product 5",
"price": "500"
}];
});
li {
padding: 10px;
}
.min-price {
width: 10px;
height: 10px;
background: green;
display: inline-block;
border-radius: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<html lang="en" ng-app="App">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body ng-controller="Controller">
<ul>
<li ng-repeat="item in priceList">
{{item.name}} - {{item.price}}$
<span class="min-price" ng-show="true"></span>
</li>
</ul>
</body>
</html>

Here is simple logic for you:-
<span class="min-price" ng-show="isMin(item.price)"></span>
$scope.isMin=function(price){
var min=$scope.priceList[0].price;
for(var i=0;i<= $scope.priceList.length-1;i++){
if(Number($scope.priceList[i].price) < min){
min=$scope.priceList[i].price;
console.log("Min"+min);
}
}
console.log("min:"+min+ " price:"+price);
if(min===price){
return true;
}else{
return false;
}
}
Plunker

Compute the minimum price in the controller, using JavaScript code, and store the result in a scope variable (minimumPrice for example).
Then use
ng-show="item.price == minimumPrice"
Hint: don't use strings to represent numbers. Use numbers.

Related

ng-repeat in ChartJS AngularJS

I have the following difficulty.
At the time of displaying the data with ng-repeat it does not show me any results.
you can see my code in CodePen
<link rel="stylesheet" href="http://jtblin.github.io/angular-chart.js/node_modules/bootstrap/dist/css/bootstrap.min.css">
<script src="http://jtblin.github.io/angular-chart.js/node_modules/angular/angular.min.js"></script>
<script src="http://jtblin.github.io/angular-chart.js/node_modules/chart.js/dist/Chart.min.js"></script>
<script src="http://jtblin.github.io/angular-chart.js/dist/angular-chart.js"></script>
<script>
var app = angular.module("RodoApp", ["chart.js"]);
app.controller("ChartController", function ($scope, $http) {
$scope.person = [
{
"name": "Rodrigo",
"number": 5,
},
{
"name": "Carlos",
"number": 11,
},
{
"name": "Arnold",
"number": 20,
}
];
$scope.labels = [];
$scope.data = [];
for (i = 0; i < $scope.person.length; i++) {
$scope.labels.push($scope.person[i].name);
$scope.data.push($scope.person[i].number);
}
$scope.options = {
legend: {
display: true,
},
title: {
display: true,
text: 'title'
} };
});
</script>
<body ng-app="RodoApp" ng-controller="ChartController">
<div ng-repeat="t in person">
<div>{{t.name}} - {{t.number}}</div>
</div>
<hr />
<div ng-repeat="options in person">
<canvas id="{{options.name}}" class="chart chart-pie" chart-options="options" chart-data="options.data" chart-labels="options.labels" />
</div>
</body>
EXAMPLE
RESULT
I need to count the IdSurveyQuestionAnswer to assign to their respective IdSurveyQuestion
There's a few issues with the code that you've posted. The key ones that I see that will get the chart rendering happening are as follows:
First, your ng-repeat is using options, but you also have a scope variable called options, and I think they are clashing (or at the very least, not doing what you think they are doing).
Changing $scope.options = {...} to $scope.chartOptions = {...}, and chart-options="options" to chart-options="chartOptions" will fix this.
Second, your ng-repeat is looking for chart-data and chart-labels inside each person. You've only defined name and number, so there is no data to display.
On this, I can see that you've iterated over the person array and dropped all the information into a scope data and labels array.
That means that while you are rendering a chart per person, you're effectively rendering the same chart each time.
A full working version follows:
<link rel="stylesheet" href="http://jtblin.github.io/angular-chart.js/node_modules/bootstrap/dist/css/bootstrap.min.css">
<script src="http://jtblin.github.io/angular-chart.js/node_modules/angular/angular.min.js"></script>
<script src="http://jtblin.github.io/angular-chart.js/node_modules/chart.js/dist/Chart.min.js"></script>
<script src="http://jtblin.github.io/angular-chart.js/dist/angular-chart.js"></script>
<script>
var app = angular.module("RodoApp", ["chart.js"]);
app.controller("ChartController", function ($scope, $http) {
$scope.person = [
{
"name": "Rodrigo",
"number": 5,
},
{
"name": "Carlos",
"number": 11,
},
{
"name": "Arnold",
"number": 20,
}
];
$scope.labels = [];
$scope.data = [];
for (i = 0; i < $scope.person.length; i++) {
$scope.labels.push($scope.person[i].name);
$scope.data.push($scope.person[i].number);
}
$scope.chartOptions = {
legend: {
display: true,
},
title: {
display: true,
text: 'title'
}
};
});
</script>
<body ng-app="RodoApp" ng-controller="ChartController">
<div ng-repeat="t in person">
<div>{{t.name}} - {{t.number}}</div>
</div>
<hr />
<div ng-repeat="options in person track by $index">
<canvas ng-attr-id="{{options.name}}" class="chart chart-pie" chart-options="chartOptions" chart-data="data" chart-labels="labels" />
</div>
</body>
While this renders the charts, the make up of the data and why you want to repeat this is something that you'll need to think about, and possible ask another question on.

VueJS v-for: remove duplicates

Is there a simple solution I can use to remove the duplicates from my v-for loop which is looping through the JSON data.
I'm using this to populate a Select option and would rather not import https://lodash.com/docs#uniq
Codepen with issue: https://codepen.io/anon/pen/JaZJmP?editors=1010
Thanks
Create a computed property that returns only those items from your array which you want/need. To remove duplicates from info, you can do new Set(this.info.map(i=>i.title.rendered) and destructure that back into an array using [...new Set(this.map(i=>i.title.rendered))]:
var vm = new Vue({
el: "#wp-vue-app",
data() {
return {
info: [{
id: 1,
status: "publish",
link: "",
title: {
rendered: "Test Name One"
},
acf: {
employee_details: {
employee_name: "Test Name",
employee_email: "Test-Email#email.co.uk",
employee_number: "123",
cost_centre_manager: "Manager Name",
manager_email: "Manager-Email#email.co.uk"
}
}
},
{
id: 2,
status: "publish",
link: "",
title: {
rendered: "Test Name"
},
acf: {
employee_details: {
employee_name: "Test Two Name",
employee_email: "Test-Two-Email#email.co.uk",
employee_number: "1234",
cost_centre_manager: "Manager Two Name",
manager_email: "Manager-Two-Email#email.co.uk"
}
}
},
{
id: 3,
status: "publish",
link: "",
title: {
rendered: "Test Name"
},
acf: {
employee_details: {
employee_name: "Test Three Name",
employee_email: "Test-Three-Email#email.co.uk",
employee_number: "12345",
cost_centre_manager: "Manager Three Name",
manager_email: "Manager-Three-Email#email.co.uk"
}
}
}
],
loading: true,
errored: false,
emp_manager: "All",
emp_cost_centre: "All"
};
},
computed: {
info_title: function() {
return [...new Set(this.info.map(i => i.title.rendered))]
},
info_employee_name: function() {
return [...new Set(this.info.map(i => i.acf.employee_details.employee_name))]
},
},
});
.container {
padding: 20px;
width: 90%;
max-width: 400px;
margin: 0 auto;
}
label {
display: block;
line-height: 1.5em;
}
ul {
margin-left: 0;
padding-left: 0;
list-style: none;
}
li {
padding: 8px 16px;
border-bottom: 1px solid #eee;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.2/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.1/vue.min.js"></script>
<div id="wp-vue-app">
<section v-if="errored">
<p>We're sorry, we're not able to retrieve this information at the moment, please try back later</p>
</section>
<section v-else>
-
<div class="row">
<div class="col">
<select class="form-control" v-model="emp_manager">
<option>All</option>
<option v-for="item in info_title" :value="item">{{ item }}</option>
</select>
<span>Selected: {{ emp_manager }}</span>
</div>
<div class="col">
<select class="form-control" v-model="emp_cost_centre">
<option>All</option>
<option v-for="item in info_employee_name" :value="item">{{ item }}</option>
</select>
<span>Selected: {{ emp_cost_centre }}</span>
</div>
</div>
<br />
</section>
</div>
https://codepen.io/anon/pen/bxjpKG
You can use a computed property to filter your info (let's say filteredInfo). Then use v-for on the filteredInfo property.

Angular + jquery ui sortable

Look in this fiddle https://jsfiddle.net/Lj0swckj/3/
I have created directive for sortable
For parent divs sortable working fine
I want same thing for childs also with containment as its parent
In the given example child1, child2, child3 can swap positions and containment will be parent1.
I tried a lot but can't find anything
Note: There can also children for a child1, child2...
(Here In this example i have added data for two levels but it can be upto four levels)
So I want a solution where sortable can work for such kind of recursive templates.
Any Help would be appreciated.
angular.module("myApp", []).
controller("myController", ['$scope', function($scope) {
$scope.fields = [{
"name": "parent1",
"level": 1,
"children": [{
"name": "child1",
"level": 2
}, {
"name": "child2",
"level": 2
}, {
"name": "child3",
"level": 2
}]
}, {
"name": "parent2",
"level": 1
}, {
"name": "parent3",
"level": 1
}];
$scope.draggableItemsOption = {
"moverElement": ".moverBtn",
"containment": ".draggable-field"
}
}]).directive("myDragDrop", ['$timeout', function ($timeout) {
return {
restrict:'A',
scope: {
myDragDrop:"="
},
link: function ($scope, element, attrs) {
var options = $scope.myDragDrop;
var $container = element;
var sortableOptions = {
/* handle: options.moverElement, */
containment: options.containment,
delay: 0
};
if($container.sortable){
$container.sortable(sortableOptions);
}
}
}
}]);
.element {
border: 1px solid #333;
padding: 10px 10px;
position: relative;
}
.element-class {
margin-left: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<div class="draggable-field" my-drag-drop="draggableItemsOption">
<div ng-repeat="data in fields">
<div class="element" ng-class="{'element-class': data.level > 1}">
{{data.name}}
<div ng-repeat="childData in data.children">
<div class="element" ng-class="{'element-class': data.level > 1}">
{{childData.name}}
</div>
</div>
</div>
</div>
</div>
</div>
Huh ! Finally Got a solution.
Actually it is pretty simple
Here look at this fiddle https://jsfiddle.net/Lj0swckj/6/
What I did is created child elems
angular.module("myApp", []).
controller("myController", ['$scope', function($scope) {
$scope.fields = [{
"name": "parent1",
"level": 1,
"children": [{
"name": "child1",
"level": 2
}, {
"name": "child2",
"level": 2
}, {
"name": "child3",
"level": 2,
"children": [{
"name": "grandChild1",
"level": 3
}, {
"name": "grandChild2",
"level": 3
}]
}]
}, {
"name": "parent2",
"level": 1,
"children": [{
"name": "child4",
"level":2
}]
}, {
"name": "parent3",
"level": 1
}];
$scope.draggableItemsOption = {
"moverElement": ".moverBtn",
"containment": ".draggable-field"
}
$scope.childDraggableItemsOption = {
"containment": "parent"
}
}]).directive("myDragDrop", ['$timeout', function ($timeout) {
return {
restrict:'A',
scope: {
myDragDrop:"="
},
link: function ($scope, element, attrs) {
var options = $scope.myDragDrop;
var $container = element;
var sortableOptions = {
/* handle: options.moverElement, */
containment: options.containment,
delay: 0
};
if($container.sortable){
$container.sortable(sortableOptions);
}
}
}
}]);
.element {
border: 1px solid #333;
padding: 10px 10px;
position: relative;
}
.element-class {
margin-left: 20px;
}
.moverBtn {
position: absolute;
top: 2px;
right: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-autocomplete/1.0.7/jquery.auto-complete.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<script type="text/ng-template" id="tree_item_renderer.html">
<div class="child-draggable-field" my-drag-drop="childDraggableItemsOption">
<div ng-repeat="data in data.children" ng-class="{'element-class': data.level > 1}">
<div class="element"> {{data.name}} ------ {{$parent.$parent.data.children.length}}</div>
<div ng-include="'tree_item_renderer.html'">
</div>
</div>
</div>
</script>
<div class="draggable-field" my-drag-drop="draggableItemsOption">
<div ng-repeat="data in fields">
<div class="element" ng-class="{'element-class': data.level > 1}">
{{data.name}}
<div ng-include="'tree_item_renderer.html'">
</div>
</div>
</div>
</div>
</div>

md-select with recursive options

I am trying to iterate through an array of categories with subcategories.
The problem. I have this array of categories:
$scope.categories = [{
"_id": 1,
"name": "Cat 1",
"categories": {
"_id": 11,
"name": "Cat 11",
"categories": {
"_id": 111,
"name": "Cat 111",
"categories": null
}
}
}, {
"_id": 2,
"name": "Cat 2",
"categories": null
}, {
"_id": 3,
"name": "Cat 3",
"categories": null
}];
As you can see, is an array of objects with subcategories, so I know that I need a recursive solution.
I need to show all the categories into a md-select (it is not necesary group it, but it will be great) and I am trying this:
<md-input-container class="md-block">
<label>Categories</label>
<md-select ng-model="selectedCategory">
<md-option ng-value="category._id" ng-repeat-start="category in categories">{{category.name}}</md-option>
<span ng-repeat-end ng-include="'subcategories'" ng-if="category.categories"></span>
</md-select>
</md-input-container>
<script type="text/ng-template" id="subcategories">
{{category.name}}
<md-option ng-value="category._id" ng-repeat-start="category in category.categories">{{category.name}}</md-option>
<span ng-repeat-end ng-include="'subcategories'" ng-if="category.categories"></span>
It works partially, but it is not the result expected.
What I want? Something like this
What I have? This code
Tell me if need more details.
Thanks
You can simply flatten your list and style elements by their nesting level.
angular
.module('app', ['ngMaterial'])
.controller('AppController', function($scope) {
$scope.categories = [{
"_id": 1,
"name": "Cat 1",
"categories": [{
"_id": 11,
"name": "Cat 11",
"categories": [{
"_id": 111,
"name": "Cat 111",
"categories": null
}]
}]
}, {
"_id": 2,
"name": "Cat 2",
"categories": null
}, {
"_id": 3,
"name": "Cat 3",
"categories": null
}];
$scope.flattenCategories = flatten($scope.categories, 0);
function flatten(categories, level) {
var flat = [];
for (var i = 0, n = categories.length, category; category = categories[i]; i++) {
flat.push({
_id: category._id,
name: category.name,
level: level
});
if (category.categories) {
flat = flat.concat(flatten(category.categories, level + 1));
}
}
return flat;
}
});
.subcategory-0 .md-text {
margin-left: 0;
}
.subcategory-1 .md-text {
margin-left: 8px;
}
.subcategory-2 .md-text {
margin-left: 16px;
}
.subcategory-3 .md-text {
margin-left: 24px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.11/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.11/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.11/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.11/angular-messages.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.4/angular-material.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.css">
<div ng-app="app" ng-controller="AppController">
<form name="myForm">
<md-input-container class="md-block">
<label>Categories</label>
<md-select ng-model="selectedCategory" name="myCategory">
<md-option ng-class="'subcategory-' + category.level" ng-value="category._id" ng-repeat="category in flattenCategories track by category._id">{{ category.name }}</md-option>
</md-select>
<!-- <pre ng-bind="flattenCategories | json"></pre> -->
</md-input-container>
</form>
</div>

backbone : Collection and View rendering

I am really confused on this one and need help. (unrelated : "up for about 36 hours now to finish somthing and this last part is just making me go crazy")
My Code
<body>
<div id="mycontainer" style="margin: 20px; ">
</div>
<script type="text/template" id="Myelement_template">
<% _.each( results, function( item, i ){ %>
<div id="Myelement" style="width: 200px; height:325px; padding: 10px; background-color: #2980b9;">
<div id="image" style="width: 190px; height: 200px; margin: auto; background-color: #f1c40f;">
<img src="<%= item.get('category').url %>" style="max-width: 90%;margin-top: 10px;">
</div>
<div id="type" style="float:left;width: 90px; height: 25px; margin-left: 5px;margin-top: 5px;background-color: #f1c40f;">
<%= item.get("category").type %>
</div>
<div id="name" style="float:left;width: 90px; height: 25px; margin-left: 10px; margin-top: 5px;background-color: #f1c40f;">
<%= item.get("category").name %>
</div>
</div>
<% }); %>
</script>
<script type="text/javascript">
$(document).ready(function() {
CategoryModel = Backbone.Model.extend({
defaults: {
url: '',
type: '',
name: ''
}
});
MyListModal = Backbone.Model.extend({
url: 'myrestapi',
defaults: {
category: CategoryModel
}
});
MyElementView = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'render'); // bind 'this' in 'render'
this.model = new MyListModal();
this.model.bind('change', this.render);
this.model.fetch(this.render);
},
el: $("#mycontainer"),
render: function(){
console.log(this.model.get("category"));
}
});
var myModelView = new MyElementView();
});
</script>
Question
My rest api will return many BaseModel objects. All of them need to be rendered. How do I do that?
console.log(this.model.get("category")); - code reaches here. not printing. debugging shows that rest api call was made and cata has been returned
How do I render all returned elements?
Sample Data returned by rest API
[
{
"category": {
"id": 1,
"name": "name1",
"type": "mytype1",
"url": "myurl1"
},
"user": {
"id": 153
},
"status": 1
},
{
"category": {
"id": 1,
"name": "name2",
"type": "type2",
"url": "url2"
},
"user": {
"id": 153
},
"status": 1
},
]

Resources