i am trying to get unique values for a nested ng-repeat
there are the two scopes i am working with
$scope.AllGames = [
{ title: "Doom", productCode: "458544", id_product: "1" },
{ title: "Wolvenstein", productCode: "457104", id_product: "2" },
{ title: "Quake", productCode: "32542687", id_product: "3" }
];
$scope.AllPrices= [
{ id_productPrice: "1", id_product: "1", price : "599" },
{ id_productPrice: "2", id_product: "1", price : "699" },
{ id_productPrice: "3", id_product: "2", price : "249" }
];
this is the html
<div ng-repeat="game in AllGames">
<div>{{game.title}} | {{game.id_product}} | {{game.title}}</div>
<div ng-init="getPriceByGame(game.id_product)">
<div ng-repeat="item in AllPrices">
{{item.price}}
</div>
</div>
and this is the controller
$scope.getAllGames = function () {
var request = 'Games';
$http({
method: 'Get',
url: uri + request
})
.success(function (data) {
$scope.AllGames = data;
})
}
$scope.getPriceByGame = function (id_product) {
var request = AllPrices/' + id_product;
$http({
method: 'Get',
url: uri + request
})
.success(function (data) {
$scope.AllPrices = data;
})
};
So the idea is that i send the id_product to the database and i get a list of prices back for that id, i would like to connect these prices for each unique product. what happens now is that the ng-init works fine and the request gets send with the id, i receive the prices for that id. In the console log i see all the prices coming in by product_id (all different arrays) but i can't seem to connect them in the html so i actually see the prices.
The last request overwrites of course all the prices for each game in the ng-repeat. How do i keep this unique? So that each product gets the prices for that id.
You could place another ng repeat to loop through the all Prices array. Every time you get new data, you push it to the array.
Don't forget to make an edit in the nested ng repeat of all prices, it should loop only through the current index
Related
I'm using fetch() to create a section which pulls and sorts listings from greenhouse api into its matching container.
I have a predefined list of departments which I have stored in the departments array. If a fetched item has a similar value as the data-dept value, then that html will be added under that container.
Here's an example, one of the items in the array is "Sales". Once fetch() is complete, two things can happen:
Either a job with the department of "sales" exists, in which case it will be appended to data-dept="sales". Note: In my code, I'm using data-dept^= to find similar names. If "sales us" exits in the api, then I want that too to be appended to [data-dept="sales"].
No jobs exist with the department of "sales". In this case, if "[data-dept="sales"]` has no child elements, hide it, as there's no point showing departments with no listings.
Current issues:
You can see by accessing the API URL that jobs with the "department" of "sales" do exist, but they do not get appended to my data-dept="sales" div (it has no child elements).
Any jobs that are not similar departments to those that are in the array need to appended to data-dept="other", but this section is also empty. For example, thee api has jobs for the "department" of "Architects". This option isn't in the array, so these jobs will need to be appended to data-dept="other".
Code:
$(function() {
fetch('https://boards-api.greenhouse.io/v1/boards/example/jobs?content=true', {})
.then(function (response) {
return response.json();
})
.then(function (data) {
appendDataToHTML(data);
})
.catch(function (err) {
console.log(err);
});
function appendDataToHTML(data) {
const mainContainer = document.getElementById("careers-listing");
// for each object, create card
for (var i = 0; i < Object.keys(data.jobs).length; i++) {
var department = data.jobs[i].departments[0].name;
department = department.replace(/\s+/g, '-').toLowerCase();
var job_title = data.jobs[i].title;
var job_location = data.jobs[i].location.name;
var html =
'<figure class="careercard" data-dept="'+ department +'">' +
'<div class="careercard__inner">' +
'<figcapton class="careercard__role">' +
'<span class="careercard__title">' + job_title + '</span>' +
'</figcapton>' +
'<div class="careercard__address">' +
'<span class="careercard__location">' + job_location + '</span>' +
'</div>' +
'</div>' +
'</figure>';
// filter card in correct parent category
if ("[data-dept^="+ department +"]") {
$(".careersIntegration__accordion-jobs[data-dept^='" + department + "']").append(html);
} else{
$(".careersIntegration__accordion-jobs[data-dept='other']").append(html);
}
}
}
/* fetch end */
$('.careersIntegration__accordion-jobs').each(function(index, obj){
console.log(this);
if ( $(this).length == 0 ) {
console.log("hide");
} else{
console.log("dont hide");
}
});
});
{% set departments = ["Sales" "Technology", "Creative", "Other"] %}
<section class="careersIntegration">
<div class="careersIntegration__listing" id="careers-listing">
{% for dept in departments %}
<div class="careersIntegration__accordion">
<div class="careersIntegration__accordion-header">
<span class="careersIntegration__accordion-dept">{{ dept }}</span>
</div>
<div class="careersIntegration__accordion-jobs" data-dept="{{ dept|lower|replace( ' ', '-' ) }}"></div>
</div>
{% endfor %}
</div>
</section>
Here is a visual guide of the layout I'm trying to achieve if it helps:
So this is not an exact answer but it does give you a good example. I just used mock data but here is the idea. Im sure there is a better way to do this but this is the quick and dirty.
Create a few variables to store the data for each department. This is a filter function that just stores anything inside the include() this will allow you to catch something like "US Sales" in the sales department.
Create a map function that takes in two paramiters the first is the variable you created earlier and the second is the name of the department which should match the name of whereever you are going to append this information.
The first part of the function creates the item using a template literal. this will create an array of all the items
The second part of the function wraps the array in a UL which is not super important but what is important is that you join the array using an empty sting.
Last part simply appends the html to the end of the department by using the name of the department as an ID and .insertAdjacentHTML("beforeend", list) which puts it before the end of the element and passes in the HTML which I have named as list
const data = [
{
title: "Lead Sales Person",
dept: "sales",
desc: "be a leader"
},
{
title: "Sales Person",
dept: "sales",
desc: "sell stuff to people"
},
{
title: "US Sales Person",
dept: "sales US",
desc: "sell stuff to people"
},
{
title: "Lead Developer",
dept: "dev",
desc: "be a leader"
},
{
title: "Developer",
dept: "dev",
desc: "Develop things and stuff"
},
{
title: "Random Guy",
dept: "other",
desc: "Do Random Stuff"
},
{
title: "Random Girl",
dept: "other",
desc: "Do Random Stuff"
}
];
let sales = data.filter(job => job.dept.includes("sales")),
dev = data.filter(job => job.dept.includes("dev")),
other = data.filter(job => job.dept.includes("other"));
mapDepartment(sales, "sales");
mapDepartment(dev, "dev");
mapDepartment(other, "other");
function mapDepartment(dept, name){
let items = dept.map(position => {
return `
<li>
<b>Title:</b> ${position.title}<br>
<b>Description:</b> ${position.desc}
</li>
`
})
let list = `<ul>${items.join("")}</ul>`;
document.getElementById(name).insertAdjacentHTML("beforeend", list)
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
margin-bottom: 1rem;
}
<div id="sales">
<h1>Sales</h1>
</div>
<div id="dev">
<h1>Development</h1>
</div>
<div id="other">
<h1>Other</h1>
</div>
So I have a multiselection dropdown with select2 and I fetch the info from a database. The thing is that prepopulating the dropdown with many values works with the example from the docs, but I also want to include an extra data field. This is how I try to populate the dropdown:
var productSelect = $('#product_ids');
$.ajax({
type: 'GET',
url: '/ajaxOrdersData/' + orderID
}).then(function (datas) {
datas.forEach(data => {
var option = new Option(data.name, data.id, true, true);
option.dataset.price = data.price;
productSelect.append(option).trigger('change');
});
productSelect.trigger({
type: 'select2:select',
params: {
data: datas.map(function (item) {
return {
text: item.nfame,
id: item.id,
price: item.price,
}
})
}
});
});
The above code does create an option tag with a data-price value but then, retrieving that value like below, doesn't work:
var products = $('#product_ids').select2('data');
The products variable doesn't have the price data attribute.
What other ways there are for me to fetch the price data attribute of all products in multiselect when clicking on a button on the DOM?
This is a solution I came up with:
var products =$('#product_ids option:selected');
And then to retrieve the value:
$.each(products, function(index, value) {
actualTotals += Number(value.dataset.price);
});
An alternative solution is to keep the .select2('data'); way of fetching the selections but instead use jquery to retrieve each elements attributes from the resulting object:
var products =$('#product_ids').select2('data');
$.each(products, function(index, value) {
price = value.element.attributes['data-price'].value;
});
Based on the result below , how can an angular for each loop be able to solve that json array of objects format ? The value is title and the id is key. Any Idea? Thank you.
mycode
me.record.questionaires = []
angular.forEach(detail.questionaires, function (value, key) {
me.record.questionaires.push({ "id": key, "title": value })
});
Formated json data (detail.questionaire result)
[
"{'sub_title': 'dsadsa', 'instruction': 'You Must',…elimit': '01:05:19', 'title': 'asdsa', 'id': 133}",
"{'sub_title': 'sdasdsa', 'instruction': None, 'cre…melimit': '05:30:09', 'title': 'asda', 'id': 131}"
]
You need to
Loop over the array
Parse the string as JSON
Push or map the appropriate values into your questionaires array (it's not clear what data you want)
me.record.questionaires = detail.questionaires.map(json => {
let { id, title } = JSON.parse(json)
return { id, title }
})
I had to change your sample formatted JSON a bit because it was giving me console errors. Please see if this helps.
angular
.module("myModule", [])
.controller("myController", function($scope) {
var me ={record: {questionaires: []}};
$scope.me = me;
var detail ={};
detail.questionaires = [
"{'sub_title': 'dsadsa', 'instruction': 'You Must','…elimit': '01:05:19', 'title': 'asdsa', id: 133}",
'{"sub_title": "sdasdsa", "instruction": "None", "cre…melimit": "05:30:09", "title": "asda", "id": 131}'
];
angular.forEach(detail.questionaires, function (value, key) {
var questionaire = JSON.parse(value.replace(/'/g, '"').replace(/id:/g, '"id":'));
me.record.questionaires.push({ "id": questionaire.id, "title": questionaire.title });
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="myModule">
<div ng-controller="myController">
<div><strong>me.record.questionaires:</strong></div>
<div ng-repeat="q in me.record.questionaires">
<div>{{q}}</div>
</div>
</div>
</div>
I am new to Angular js and I want to try the following.
I have an Object Array that come from Database. This is the url(example): http://localhost:3000/items/showAll
I have yet implemented the Add, Edit, Update, Delete (Crud operation in backend with nodejs and express js and frontend with angularjs) but my problem is with the checkbox.
I have in a table in my database a field "state", typ boolean default 0 (1 or 0 value).
I have a list of items(for example 100) and want to select with a checkbox in ng-repeat one or more items and send the value(1) to my filed state in the database. My logic is: I need to bind a single item id with the checkbox, then add a value to the checkbox and if is checked send it to the database.
<input type="checkbox" ng-model="state" parse-int ng-true-value="'1'" ng-false-value="'0'" class="form-check-input" >
[{"id":1,"name":"item1","state":0}]
What can I in my controller do?
Updated:
Code: Controller
$scope.createState = function() {
var postItem = {
id : $scope.id,
state : $scope.state
};
itemsService
.createItem(postItem)
.then(
function successCallback(response, data) {
$scope.clearForm();
},
function errorCallback(error, data, status, haders, config) {
console.log("Error getting: " + data);
}
);
};
Service:
var pathItems = "/items/add";
this.createItem = function(postItem) {
return $http.post(pathItems, postItem)
};
html ng-repeat:
<input type="checkbox" ng-true-value="1" ng-false-value="0" ng-model="item.state" ng-click="createState(item.id)">
Update the database, api
addItem: function(item, id, callback) {
return database.query("Update items SET state=? WHERE id=?", [item.state, id], callback);
},
router.post('/update/', function(req, res, next) {
items.addItem(req.body, function(error, count) {
if (error) {
res.json(error);
} else {
res.json(req.body);
}
});
});
This can update the database and I can do this from a bootstrap modal. I wanted to do this with a list of one checkbox per user, but I don't now what to do in AngularJS.
As far as I can understand from your question every time a checkbox is clicked you want to make an API call with the appropriate state. Attach the state to the ng-model of the checkbox. Then on ng-click call a function that will make an API call to update the database,
You can have a look at this code pen for the demo
HTML
<body ng-app="app" ng-controller="controller">
<div ng-repeat="item in data">
{{item.name}}
<input type="checkbox" ng-true-value="1" ng-false-value="0" ng-model="item.state" ng-click="makeAPICall(item.id)"><br>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
</body>
Javascript
angular.module("app", [])
.controller("controller",
function($scope) {
$scope.data = [
{ id: 1, name: "item1", state: 0},
{ id: 2, name: "item2", state: 1},
{ id: 3, name: "item3", state: 0},
{ id: 4, name: "item4", state: 1},
{ id: 5, name: "item5", state: 0}
];
$scope.makeAPICall = function(itemID){
console.log("Item with id "+itemID+" was changed");
// Make API call here
};
}
);
The code updated in my question can update the database. For example, if userID=1, check/uncheck the user and update the database. In Angularjs HTML I can do this with a bootstrap modal. Click to a button and check/uncheck the checkbox.
I have the following array:
[{
"Id": 3,
"Name": "A"
},
{
"Id": 3,
"Name": "B"
},
{
"Id": 3,
"Name": "C"
}]
I am using this in the following Angular view:
<select ng-model="selectedCategory" ng-options="category.Name for category in categories"></select>
<pre>{{selectedCategory | json}}</pre>
<button type="button" ng-click="move()">Move</button>
The controller looks like:
var moveCategoryController = function ($scope, category, categoriesService) {
var getCategories = function () {
categoriesService.getCategories()
.success(function (result) {
$scope.categories = [];
for (var i = 0; i < result.Results.length; i++) {
var cat = result.Results[i];
if (cat.Id !== category.Id) {
$scope.categories.push(cat);
}
}
$scope.selectedCategory = $scope.categories[0];
})
.error(function () {
$scope.errorMessage = "There was a problem loading the categories.";
});
};
getCategories();
$scope.move = function () {
alert($scope.selectedCategory.Name);
};
}
bpApp.controller("moveCategoryController", moveCategoryController);
For info, the category object injected into the controller is a category object (the controller is being used in a modal and the category is passed to it from the parent page).
The Problem
On loading, the select is bound to the data fine, and when the user changes the select list the <pre> content updates correctly with the newly selected category.
The problem is when I click the Move button, which calls the move() function on the controller scope, the selectedCategory property of the scope has not been updated. For example, if I select the category "B", the alert still pops up with "A".
So, it seems that the ng-model is updated in the view, but not in the controller?!