$$hashKey match and selected value for select menu - javascript

I am trying to set selected option for the select menu but its not working because data that I am sending to ng-model has different $$hashKey from data in the select menu and $$hashKey holding for values.
<select class="form-control" ng-model="selManga" ng-options="manga.seri for manga in mangalar">
<option value="">Manga Seçin</option>
</select>
<select ng-change="selPage = 0" ng-model="selChapter" ng-options="selManga.randomword.indexOf(chapter) as chapter.klasor for chapter in selManga.randomword">
<option value="">Bölüm</option>
</select>
<select ng-model="selPage" ng-options="selManga.randomword[selChapter].yol.indexOf(page) as selManga.randomword[selChapter].yol.indexOf(page) + 1 for page in selManga.randomword[selChapter].yol">
</select>
I google it to get around with this people says track by but I have to use as. So is there a another way to get around it?
Selected value for first select menu is working but second one is not working. Here is plunker.http://plnkr.co/edit/3V8JSF2AU01ZZNPfLECd?p=info
.controller('nbgCtrl',function ($scope, MMG, $stateParams) {
var milo = $stateParams.serix;
var musti = $stateParams.klasor;
MMG.adlar.success(function(loHemen) {
var i, miloMangaInArray;
for (i=0; i<loHemen.length; i++) {
if (loHemen[i].seri===milo) {
miloMangaInArray = loHemen[i];
break;
}
};
var a;
for (a=0; a<miloMangaInArray.randomword.length; a++) {
if(miloMangaInArray.randomword[a].klasor===musti) {
break;
}
}
$scope.mangalar = loHemen; //JSON Data
$scope.selManga = $scope.mangalar[i]; // First select menu's ng-model and its working.
$scope.selChapter = $scope.mangalar[i].randomword[a]; //Second select menu's ng-model and its not working due to no matching JSON data.
});
$scope.next = function (manga, chapter, page) {
var nextPage = page + 1;
if (angular.isDefined(manga.randomword[chapter].yol[nextPage])) {
$scope.selPage = nextPage;
} else if (angular.isDefined(manga.randomword[chapter + 1])) {
$scope.selChapter = chapter + 1;
$scope.selPage = 0;
}};
})

Dude here you go, a js fiddle for the solution
http://jsfiddle.net/yw248mfu/2/
the method I used here is indexOf to get the index of the page in the array for the last select only ,,
and this is not the best solution as it will have to apply index of every time the digest loop run ,,
I can think of a number of different solutions to this ,,
1- you can extract the id of the page from the name of the image itself
2- you can map the pages array to be a list of objects with the following schema
[{"index":1,"img":"00.jpg"},{"index":2,"img":"01.jpg"},{"index":3,"img":"02.jpg"}]
you can do the second option with this piece of code
pages.map(function(d,i){return {"index":i,"img":d};});
crouch74

I think you should embrace the AngularJS way of handling models and bindings. So, instead of keeping track of all the different indexes through your view code, you can simply let ng-select assign references to parts of your model (via ng-model). By changing the HTML and controller slightly, you can simplify some of the code, and it will actually work, too.
First, make a shared $scope.model = {…} object available on the $scope. Then, change the HTML to
<select ng-model="model.selManga" ng-options="manga.seri for manga in mangalar">
<option value="">Manga Seçin</option>
</select>
<select ng-model="model.selChapter" ng-options="chapter.klasor for chapter in model.selManga.randomword" ng-change="model.selPage = model.selChapter.yol[0]">
<option value="">Bölüm</option>
</select>
<select ng-model="model.selPage" ng-options="page as model.selChapter.yol.indexOf(page) + 1 for page in model.selChapter.yol">
</select>
<img class="picture" ng-src="http://baskimerkeziankara.com/{{model.selPage}}" ng-click="next(model.selPage)">
After that, change the controller is changed accordingly:
.controller('nbgCtrl', function($scope, MMG, $stateParams) {
var model = {
selManga: undefined,
selChapter: undefined,
selPage: undefined
};
$scope.model = model;
MMG.adlar.success(function _init(loHemen) {
for (var i = 0; i < loHemen.length; i++) {
if (loHemen[i].seri === $stateParams.serix) {
model.selManga = loHemen[i];
break;
}
}
for (var a = 0; a < model.selManga.randomword.length; a++) {
if (model.selManga.randomword[a].klasor === $stateParams.klasor) {
model.selChapter = model.selManga.randomword[a];
break;
}
}
model.selPage = model.selChapter.yol[0];
$scope.mangalar = loHemen;
});
$scope.next = function _next(page) {
var pageIndex = model.selChapter.yol.indexOf(page);
if (angular.isDefined(model.selChapter.yol[pageIndex + 1])) {
model.selPage = model.selChapter.yol[pageIndex + 1];
} else {
var chapterIndex = model.selManga.randomword.indexOf(model.selChapter);
if (angular.isDefined(model.selManga.randomword[chapterIndex])) {
pageIndex = 0;
model.selChapter = model.selManga.randomword[chapterIndex + 1];
model.selPage = model.selChapter.yol[pageIndex];
}
}
console.log('manga', model.selManga.seri,
'chapter', model.selChapter.klasor,
'selPage', pageIndex + 1);
};
})
I've created a forked Plunker that shows how this works (and this solution actually works): http://plnkr.co/edit/2aqCUAFUwwXuGQHpuooj

Related

binding data to attribute by iterating

I have the following ForEach in my razor where i am setting some values.
It works fine. I can see my all values.
#foreach (var item in Model.ConsultantDetails.ScopeOfSevrices)
{
<div id="optionValue" class="item" data-value=>#item.Name</div>
}
Then i have an ajax call and get the result back.
I want to set this data back to same DIV by iterating
$.each(data.ConsultantDetails.ScopeOfSevrices, function (index) {
$('optionValue').attr("data-value=>", data.ConsultantDetails.ScopeOfSevrices[index].Name);
});
No luck, how do i achieve that?
use for loop instead of foreach, so we can set seprate id to each iteration
dont use data-value=> , instead use data-value=" " or some dummy value (here we use : item.Name)
#for (int i = 0; i < Model.ProductTypeService.Count; i++)
{
var item = Model.ProductTypeService[i];
var id = "optionValue" + i;
<div id="#id" class="item" data-value="#item.Name">#item.Name</div>
}
finally, in jquery, we can assign attribute value based on div id
$.each(data.ProductTypeService, function (index) {
$('#optionValue' + index).attr("data-value", data.ProductTypeService[index].Name + index); // + index // just to see different value
});

Displaying data on the page from the data gotten from parse

I have offers table and users table on parse server. I did a query for he offers table and it worked great (both console log and html - I had issues with async and the Q.promise helped). Now I'm trying to add two elements that are in the users table. I get it on the console, but not on the page. Here is what I have on the offers.service:
this.getAllOffers = function () {
var Q = $q.defer();
console.log('getAllOffers called');
//all offers filter is selected
this.allOffersFilter = false;
var offers = Parse.Object.extend("Offer");
var exchanges = Parse.Object.extend("Exchanges");
var users = Parse.Object.extend("User");
var query = new Parse.Query(offers);
var userQuery = new Parse.Query(users);
var results = [];
query.descending("createdAt");
query.limit(4);
userQuery.find().then(function(users) {
for (i = 0; i < users.length; i++) {
foundUsers = users[i];
query.find().then( function(offers){
for(i = 0; i < offers.length; i++){
found = offers[i];
var result = {};
result.date = found.get("createdAt");
result.price = found.get("price");
result.status = found.get("accepted");
result.lastName = foundUsers.get("lastName");
result.companyName = foundUsers.get("companyName");
console.log(result.companyName);
console.log(result.price);
}
});
results.push(result);
}
Q.resolve(results);
});
return Q.promise;
};
Then my HTML:
<!--List of offers-->
<div class="col-md-3">
<h4>List of offers</h4>
<div ng-if="offersList">
<div ng-repeat="offer in offersList">
<div class="offer card">
<div>{{offer.username}}</div>
<div>{{offer.companyName}}</div>
<div>{{offer.date}}</div>
<div>{{offer.price}}</div>
<div>{{offer.status}}</div>
</div>
</div>
</div>
<div ng-if="!(offersList)">There are no offers</div>
</div>
Then my component:
angular.module('offersPage')
.component('offersPage', {
templateUrl: 'pages/offers-page/offers-page.template.html',
controller: function(AuthService, PageService, OffersService,
$scope) {
// Functions for offers-page
// Check if user is logged in and verified on page load
AuthService.userLoggedin(function(loggedIn, verified) {
if(!verified) {
PageService.redirect('login');
}
});
this.$onInit = function() {
OffersService.getAllOffers().then(function(offersList) {
$scope.offersList = offersList;
});
}
}
});
THANKS IN ADVANCE !
You are resolving $q before results is populated, so, you list is empty.
I don't know about Parse server, but if userQuery.find().then is async, then need to move Q.resolve(results); inside it, or probably inside query.find().then.
When you do an ng-if in angularjs it literally takes out the element and when it puts it in it is as a child scope. To fix this you need to make sure and put $parent on any child element inside an ng-if. See below. Make sure to use track by $index to when you are doing repeats its good practice. Also notice you dont need to $parent anything in the repeat since it is referencing offerwhich is defined.
Code:
<div ng-if="offersList">
<div ng-repeat="offer in $parent.offersList track by $index">
<div class="offer card">
<div>{{offer.username}}</div>
<div>{{offer.companyName}}</div>
<div>{{offer.date}}</div>
<div>{{offer.price}}</div>
<div>{{offer.status}}</div>
</div>
</div>
</div>

How to group all product of single brand together - angular JS

Please see this JS fiddle link.
http://jsfiddle.net/4Dpzj/174/
This is the logic for group by
app.filter('groupBy', ['$parse', function ($parse) {
return function (list, group_by) {
var filtered = [];
var prev_item = null;
var group_changed = false;
// this is a new field which is added to each item where we append "_CHANGED"
// to indicate a field change in the list
//was var new_field = group_by + '_CHANGED'; - JB 12/17/2013
var new_field = 'group_by_CHANGED';
// loop through each item in the list
angular.forEach(list, function (item) {
group_changed = false;
// if not the first item
if (prev_item !== null) {
// check if any of the group by field changed
//force group_by into Array
group_by = angular.isArray(group_by) ? group_by : [group_by];
//check each group by parameter
for (var i = 0, len = group_by.length; i < len; i++) {
if ($parse(group_by[i])(prev_item) !== $parse(group_by[i])(item)) {
group_changed = true;
}
}
}// otherwise we have the first item in the list which is new
else {
group_changed = true;
}
// if the group changed, then add a new field to the item
// to indicate this
if (group_changed) {
item[new_field] = true;
} else {
item[new_field] = false;
}
filtered.push(item);
prev_item = item;
});
return filtered;
};
I want to group all the products together.
what changes i need to do ?
I come up with this in my mind. Without using any custom filters.
I simply use this ng-repeat syntax :
ng-repeat="(key,item) in MyList | orderBy:orderKey"
Thanks to it i can get the key to compare the value with the previous object.
Here is my ng-show attribute. It can be improved by sorting the list somewhere else (like in the controller)
<h2 ng-show="(MyList | orderBy:orderKey)[key-1][orderKey] !== (MyList | orderBy:orderKey)[key][orderKey]"
Thanks to this you can populate your var "orderKey" with any of your attribute name and this will works.
See it working in this JSFiddle
Hope it helped.
EDIT :
I think it would be a bit cleaner to use a temporary list to manage the visual order (see it in this JSFiddle):
JS :
$scope.orderList = function(){
$scope.orderedList = $filter('orderBy')($scope.MyList,$scope.orderKey);
}
HTML :
ng-change="orderList()" To trigger the list sort
The cleaner ng-repeat / ng-show
<div ng-repeat="(key,item) in orderedList">
<h2 ng-show="orderedList[key-1][orderKey] !== orderedList[key][orderKey]">{{item[orderKey]}} </h2>
<ul>
<li>{{item.ProductName}}</li>
</ul>
</div>
Have a look at this:
http://jsfiddle.net/4Dpzj/176/
<div ng-repeat="item in MyList | orderBy:['SubCategoryName','BrandName'] | groupBy:['SubCategoryName']" >
<h2 ng-show="item.group_by_CHANGED">{{item.SubCategoryName}} </h2>
<ul>
<li>{{item.ProductName}} --- {{item.BrandName}}</li>
</ul>
</div>

Angular Chosen default not working with object

I am using https://github.com/localytics/angular-chosen to allow for select tags with search capability for many options.
The problem I'm having is with preselecting an option on an already saved vendor object. When creating a new one there is now issue, but if we're viewing an existing vendor, I want to show the vendor's name in the select box, rather than the placeholder.
<select chosen
ng-model="myVendor"
ng-options="vendor['public-id'] as vendor.name for vendor in vendors"
data-placeholder="Nah">
</select>
And in my controller, I'm setting the model by hand $scope.myVendor = "Some value"
The problem is that I'm populating the options with an object, instead of a key/value. I found an example of it working with a key/value, but haven't had success adapting this to objects as options.
I've even tried setting myVendor to the matching object that I want selected, with no luck.
Plunker of issue
I updated the plunker and change my previous changes on the plugin. this was not the issue. I don't understand how it was giving me errors there.
The solution is to track with an object and two functions the id and the name:
// Controller
$scope.vendors = [
{
"public-id": "1234",
"name": "stugg"
},
{
"public-id": "4321",
"name": "pugg"
}
];
$scope.myVendor = {name: "pugg", id:""};
$scope.updateMyVendorName = function () {
var found = false,
i = 0;
while (!found && i < $scope.vendors.length) {
found = $scope.vendors[i]['public-id'] === $scope.myVendor.id;
if (found) {
$scope.myVendor.name = $scope.vendors[i].name;
}
i++;
}
}
findVendorByName();
function findVendorByName () {
var found = false,
i = 0;
while (!found && i < $scope.vendors.length) {
found = $scope.vendors[i]['name'] === $scope.myVendor.name;
if (found) {
$scope.myVendor.id = $scope.vendors[i]['public-id'];
}
i++;
}
}
// template
<select chosen class="form-control span6" ng-options="vendor['public-id'] as vendor.name for vendor in vendors" ng-model="myVendor.id" ng-change="updateMyVendorName()">
{{myVendor.name}}

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();
})

Categories