Sort/GroupBy files pre-uploaded using AngularJS - javascript

I want to group my files before to upload them by extension(The extension can not be defined in the mime type attribute defined by the upload infos. So I used groupBy defined by angular-filter and instead to put an attribute('file.name' for example) to the filter Im using a function to get the extension.
So I want my pre-loaded files appears like this:
Extension1:
file3.Extension1
file1.Extension1
Extension2:
file4.Extension2
file2.Extension2
This is my EXAMPLE
Also my code:
<ul>
<li ng-repeat="f in files | groupBy: fileExtension" style="font:smaller">
{{f.name}}
</li>
</ul>
$scope.fileExtension = function(file) {
return file.name.split('.').pop();
};
Any suggestion is appreciated!

I would transform your list of file names into a list of file groups inside of an ngController or service. Binding to this transformed collection becomes trivial in the view.
$scope.groups = groupByExt(filenames);
function groupByExt(filenames) {
var extensions = [];
var groups = [];
angular.forEach(filenames, function(item) {
var extension = item.substring(item.lastIndexOf(".")+1);
if (!extensions[extension]) {
var group = { name: extension, files: [] };
extensions[extension] = group;
groups.push(group);
group.files.push({ name: item });
}
else {
var group = extensions[extension];
group.files.push({ name: item});
}
});
return groups;
}
HTML
<ul>
<li ng-repeat="group in groups">
{{ group.name }}
<ul>
<li ng-repeat="file in group.files">
{{ file.name }}
</li>
</ul>
</li>
</ul>
Demo
You can also set up $watchers so that when the original filenames list changes, it updates the file groups:
$scope.$watchCollection('filenames', function(newVal, oldVal) {
if(newVal !== oldVal) {
$scope.groups = groupByExt(newVal);
}
});
Demo
I would avoid filters because filters should not change the references of the underlying items (infinite digest issue)

Related

Angularjs search product by price (from price to price)

I'm trying to add filter for searching the product by from price to price. I have following array in json format as $scope.products in the controller.
[
{"product_id":"1","product_price":"185"},
{"product_id":"2","product_price":"45"},
{"product_id":"3","product_price":"123"},
{"product_id":"4","product_price":"23"},
{"product_id":"5","product_price":"776"}
]
And below is the loop in html
<ul class="items">
<li ng-repeat="product in products | filter:{product_name: findname} | sizeFilter:(size_arr|filter:{on:true})" >
<strong>{{product.product_name | CapsFirst}}</strong>
<strong>({{product.product_category}})</strong>
<strong>({{product.product_size}})</strong>
<strong>({{product.product_color}})</strong>
</li>
</ul>
In the view I want to add two input fields for searching the products by price.
<input type="number" ng-model="from_price" />
<input type="number" ng-model="to_price" />
Can anyone guide me that I can develop in proper way. I've searched about it but couldn't found a tutorial, I'm not expertise in angularjs. Thank You...
Here's an example on plunkr of what you've been asking for. I have added a product name in order to distinguish them, try it.
https://plnkr.co/edit/NKos4x9eeB5dZQaypurg?p=preview
app.filter('sizeFilter', [function() {
return function(values, config) {
if (config.enabled) {
var filterResult = [];
angular.forEach(values, function(value) {
if (value.product_price >= config.from_price && value.product_price <= config.to_price) {
filterResult.push(value);
};
});
return filterResult;
}
return values;
}
}]);
In HTML
<li ng-repeat="product in products |rangePrice:
{'toPrice':to_price,'fromPrice':from_price}">
In JavaScript
app.filter('rangePrice', function() {
return function( items, rangePrice ) {
var filteredValue= [];
var toPrice= parseInt(rangePrice.toPrice);
var fromPrice= parseInt(rangePrice.fromPrice);
angular.forEach(items, function(item) {
if( item.product_price>= toPrice&& item.product_price<= toPrice) {
filteredValue.push(item);
}
});
return filteredValue;
};
});

How to render data with Handlebars and jQuery

I have this html where I need to render the data
default.hbs
<div class="chart-container" data-action="chartContainer">
<ul>
<li class="department">
<h3>Enterprise</h3>
<ul class="sections">
// HERE I NEED TO RENDER THE DATA IN AN <li> TAG
</ul>
</li>
</ul>
</div>
and here is the code
APP.chartContainer = (function () {
var Handlebars = window.Handlebars;
var bindEventsToUI = function () {
$.getJSON('maindata.json')
.done(function(data) {
localStorage.setItem('jsonData', JSON.stringify(data));
}).fail(function(err) {
console.log(err);
});
var chartContainerTemplate = $(".chart-container").html();
var theTemplate = Handlebars.compile(chartContainerTemplate);
var getData = localStorage.getItem('jsonData');
var iterateObj = $.each(JSON.parse(getData), function(key, val) {
return val;
});
var theCompiledHtml = theTemplate(iterateObj[0].enterprise);
$(".sections").append(theCompiledHtml);
};
var init = function (element) {
bindEventsToUI();
};
/**
* interfaces to public functions
*/
return {
init: init
};
}());
the function iterateObj returns this
[
{
"enterprise":[
{
"id":"10",
"name":"Hellen Quesada",
"role":"Principal Software Engineer"
},
{
"id":"11",
"name":"Jonathan Chavez",
"role":"Principal Creative Engineer"
}
]
},
{
"consumer":[
{
"id":"18",
"name":"Helga Martinez",
"role":"Production Manager"
},
{
"id":"19",
"name":"Leroy Bernard",
"role":"Sr. Software Engineer"
}
]
}
]
but all I need to render for now is the enterprise part of the data, that is why in my function I am doing iterateObj.[0].enterprise but I am not getting anything in the DOM yet, how do I iterate properly in the over the object in order to get the rendering of the data I need?
What am I missing ?
The template needs to be a script not html. The script can contain the needed html though.
<script id="foo" type="text/x-handlebars-template">
<div class="chart-container" data-action="chartContainer">
<ul>
<li class="department">
<h3>Enterprise</h3>
<ul class="sections">
//Not really sure what you want here
//But access the data like this
<li>{{enterprise.id}}</li>
</ul>
</li>
</ul>
</div>
</script>
Then you compile the template (ie the script):
//var chartContainerTemplate = $(".chart-container").html();
//rename the script to a better id
var chartContainerTemplate = $("#foo").html();
Lastly I would highly suggest reading the docs. There are ways of looping and accessing data. The above template is very basic.

split string using angularjs

I'm trying to split a string pulled from a JSON array in angular. I've tried using the angular {{filter}} but not sure I'm on the right track. I want each tag in it's own link. ie <a ng-href="">tall</a> | <a ng-href="">large</a> etc...
<body ng-app="feedApp">
<div ng-controller="FeedController as feedCtrl">
<ul class="tags">
<li>Tags: </li>
<li>
<a ng-href="http://www.example.com/{{feed.tags|filter:' '}}" ng-repeat="feed in feedCtrl.feeds">{{feed.tags|filter:' '}} | </a>
</li>
</ul>
</div>
</body>
JS
var app = angular.module('feedApp', [ ]);
app.controller('FeedController', ['$http', '$scope',function($http, $scope){
var array = this;
array.feeds = [ ];
$http.get('tags.json').success(function(data){
array.feeds = data;
});
JSON
[
{
"tags": "tall large winner skill"
},
{
"tags": "short knowledge"
},
]
I have a PLUNKER that shows the code above - thanks
I suggest you to manipulate the data read from tags.json producing a simple array with a tag for each element. To do so, you can use simple JavaScript code:
$http.get('tags.json').success(function(data) {
var splittedTags = data.map(function(e) {
return e.tags.split(' ');
});
array.feeds = splittedTags.reduce(function(a, b) {
return a.concat(b);
});
});
First I use Array.prototype.map() to extract from every object inside data the value of tags attribute and split it. This produce an array of array. I use the Array.prototype.reduce() to flatten the array and produce and array with the single tags.
Then, in the HTML page I remove the Angular.js filter and use directly the feed value:
<li>
<a ng-href="http://www.example.com/{{feed}}" ng-repeat="feed in feedCtrl.feeds">{{feed}} | </a>
</li>
Here you can find the PLUNKER with the code.
Here is how you can do it.
First you need to split the string by defining the delimiter (in your case is space). You then assign it to your scope:
var app = angular.module('feedApp', []);
app.controller('FeedController', ['$http', '$scope',function($http, $scope){
var array = this;
array.feeds = [ ];
var strings = [];
$http.get('tags.json').success(function(data){
data.map(function(elem) {
strings.push(elem.tags.split(' '));
});
array.feeds = strings;
});
}]);
If you are done with this in your template you can iterate over your array with ng-repeat recursively:
<body ng-controller="FeedController as feedCtrl">
<ul class="tags">
<li>Tags: </li>
<li>
<div ng-repeat="feeds in feedCtrl.feeds">
<div class="link" ng-repeat="(key, value) in feeds">
<a ng-href="http://www.example.com/{{value}}" >{{value}} | </a>
</div>
</div>
</li>
</ul>
</body>
Here is the working plunkr.

Filter ng-repeat with dropdown without duplicating the dropdown options

The same way, I can manually do filter: { category : 'Popular'} in ng-repeat, I'd like to be able to do the same thing with the dropdown.
I was able to make the basics work. I have two problems: I don't want the categories to duplicate themselves in the dropdown, I'd like to be able to see everything categorized "Popular" when I select "Popular" in the dropdown.
Here is my HTML:
<div ng-controller="SuperCtrl" class="row">
<ul class="small-12 medium-12 columns">
<select ng-model="find" ng-options="entry.category for entry in parsedEntries"><option value="">Select Category</option></select>.
<li ng-repeat="entry in parsedEntries | filter: find">
<strong>{{ entry.title }} </strong><br>
{{ entry.description }}
</li>
</ul></div>
Here is the controller:
app.controller('SuperCtrl', ['$scope', '$http', function($scope,$http) {
var url = 'https://spreadsheets.google.com/feeds/list/1lZWwacSVxTD_ciOsuNsrzeMTNAl0Dj8SOrbaMqPKM7U/od6/public/values?alt=json'
var parse = function(entry) {
var category = entry['gsx$category']['$t'];
var description = entry['gsx$description']['$t'];
var title = entry['gsx$title']['$t'];
return {
category: category,
description: description,
title: title
};
}
$http.get(url)
.success(function(response) {
var entries = response['feed']['entry'];
$scope.parsedEntries = [];
for (key in entries) {
var content = entries[key];
$scope.parsedEntries.push(parse(content));
}
});
}]);
Got it working as you want with :
<select ng-model="find" ng-options="entry.category as entry.category for entry in parsedEntries | unique: 'category'">
The unique filter is from angular-filter. It requires to add 'angular.filter' you to your modules dependencies:
var app = angular.module('myApp', ['angular.filter']);
See fiddle
NB: Not a problem by itself but I took the <select> element out of the <ul> one.
Just put unique categories into in a string array called categories, sort the array, and display it with ng-options:
<select ng-model="find" ng-options="category as category for category in categories"><option value="">Select Category</option></select>.
Append this to your code after your parse function, and delete the $http.get you had. This defines a contains function and builds the array at the same time the objects come back:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
};
$http.get(url)
.success(function(response) {
var entries = response['feed']['entry'];
$scope.parsedEntries = [];
$scope.categories = [];
for (key in entries) {
var content = entries[key];
var obj = parse(content);
$scope.parsedEntries.push(obj);
if (!contains($scope.categories, obj.category))
{
$scope.categories.push(obj.category);
}
}
$scope.categories.sort();
})

Add a line break or similar when in a for loop and a value changes - jQuery

I have a db table with users and I am creating a hierarchy system.
Currently the top users (with a 1 hierarchy) are shown, and then when clicked I gather all the related users via ajax and display below.
These users have 4 or 5 tiers for their hierarchy. 1 being the highest level.
I want to be able to make a new line of users each time the hierarchy changes.
I query the db and fetch all the users with an order by of the hierarchy number, I then put them into an array, return with JSON and loop through in jQuery:
for(var i=0; i<data.userArray.length; i++){
var user = data.userArray[i];
$appendedItems.append(SHOW ALL USERS HERE);
}
Lets say the array is:
hierarchy => 2,
hierarchy => 2,
hierarchy => 2,
hierarchy => 3,
hierarchy => 3,
hierarchy => 4,
Each time the hierarchy changes, I would like to show a line break or something just to put the users on a new line to denote a lower level.
Thanks.
how I'd do it, obviously your case will be different but you can get the idea:
markup:
<ul id="#users">
<li data-user-id="3">david</li>
<li data-user-id="4">frank</li>
</ul>
jQuery:
$('#users').on('click', 'li:not(.exploded)', function() {
var $user = $(this).addClass('exploded'),
userId = $user.data('userId'),
url = '/getUsersChildres?user=' + userId;
$.getJSON(url).then(function(data) {
$('<ul>', {
html: $.map(data.userArray, function(i, user) {
return $('<li>', {
text: user.name,
data: {
'userId': user.id
}
});
})
}).appendTo($user);
}, function() {
$user.removeClass('exploded');
});
return false;
});
should end up with:
<ul id="#users">
<li data-user-id="3" class="exploded">david
<ul>
<li data-user-id="13">jack</li>
<li data-user-id="14">paul</li>
</ul>
</li>
<li data-user-id="4">frank</li>
</ul>

Categories