Creating a remove and add button in JavaScript for a cart - javascript

I'm working on a project to create a shopping cart in a beginners JavaScript course. So far I've managed to add items to a cart and multiply their value to a subtotal. Where I'm failing is that my + and - aren't working, so I cannot add an idem twice? I get the
Uncaught TypeError: cannot set property 'innerHTML' of null
And I have read that To recap, this error occurs commonly when you try to modify an HTML element that has not appeared yet on the page. The solution is to move your JavaScript code from the head tag below the HTML element.
New to web-development... anyways below is my code.
const products = [{
"id": 1,
"name": "Aloe Vera",
"origin": "Nederländerna",
"description": "Lättskött suckulent med tjocka gröna blad. En av världens äldsta läkeväxter",
"height": "Höjd: 120cm",
"care": "Lättskött suckulent som trivs ljust, men undvik direkt solljus.",
"image": "img/alovera.jpeg",
"price": 100
},
{
"id": 2,
"name": "Citronfikus",
"origin": "Danmark",
"description": "En vacker växt med blanka, små gröna blad.",
"height": "Höjd: 50cm",
"care": "Passar bra i uterummet sommartid.",
"image": "img/citronfikus.jpeg",
"price": 150
},
{
"id": 3,
"name": "Hampa",
"origin": "Jamaica",
"description": "En fin växt med väldigt vackra blad med magiska egenskaper.",
"height": "Höjd: 50-100cm",
"care": "Passar bra i uterummet sommartid, vänt mot öst eller väst.",
"image": "img/hemp.jpg",
"price": 200
}
];
/* This section her renders all the items I've added to the cart, it also uses the id's that my objects have saved in the array that I created. I try to generate this button when rendering an item but it doesn't change the amount of items... I don't know why */
function renderCartItems() {
cartItemsEl.innerHTML = ""; // clear cart element
cart.forEach((item) => {
cartItemsEl.innerHTML += `
<div class="cart-item">
<div class="item-info" onclick="removeItemFromCart(${item.id})">
<img src="${item.image}" alt="${item.name}">
<h4>${item.name}</h4>
</div>
<div class="unit-price">
${item.price}:-
</div>
<div class="units">
<div class="btn minus" onclick="changeNumberOfUnits('minus', ${item.id})">-</div>
<div class="number">${item.numberOfUnits}</div>
<div class="btn plus" onclick="changeNumberOfUnits('plus', ${item.id})">+</div>
</div>
</div>
`;
});
}
/* this section creates a function that is supposed to update the numberOfUnits with the - and + buttons that are generated from the code above. But when I press them nothing happens, it doesn't change the number of units and is never updated...*/
function changeNumberOfUnits(action, id) {
cart = cart.map((item) => {
let numberOfUnits = item.numberOfUnits;
if (item.id === id) {
if (action === "minus" && numberOfUnits > 1) {
numberOfUnits--;
} else if (action === "plus" && numberOfUnits < 1) {
numberOfUnits++;
}
}
return {
...item,
numberOfUnits,
};
});
updateCart();
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons#1.5.0/font/bootstrap-icons.css">
<div class="app-container">
<div class="app-bg">
<div class="left-side"></div>
<div class="right-side"></div>
</div>
<header>
</header>
<div class="products-list">
<div class="products">
<!-- render porducts here -->
</div>
<div class="cart">
<div class="cart-header">
<div class="column1">Vara</div>
<div class="column2">Pris</div>
<div class="column3">Antal</div>
</div>
<div class="cart-items">
<!-- render cart items here -->
</div>
<div class="cart-footer">
<div class="subtotal">
Totalt (0 varor): 0
</div>
<div class="checkout">
Vidare till betalning
</div>
</div>
</div>
</div>

Oh man so annoying! But I found the solution, in order to be able to increase the amount of items in the cart I have to check if the value is > or < then the actual number added so I solved it like this.
// change number of units for an item
function changeNumberOfUnits(action, id) {
cart = cart.map((item) => {
let numberOfUnits = item.numberOfUnits;
if (item.id === id) {
if (action === 'minus' && numberOfUnits >= numberOfUnits) {
numberOfUnits--;
} else if (action === 'plus' && numberOfUnits <= numberOfUnits) {
numberOfUnits++;
}
}
return {
...item,
numberOfUnits,
};
});
updateCart();

Related

How can I filter contents based on rating

This is my first project and I am trying to build a product filter. I created search and category filter which is working properly, but I am not able to create filter for rating.
This is my code for reference:
<div class="heading">
<h6 class="mb-3">Filter By Area</h6>
</div>
<div class="form-check" v-for="filter in filters" :key="filter">
<input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault1"
#click="() => filterAccommodations(filter)">
<label class="form-check-label area-filter-each" for="flexRadioDefault1">
{{ filter }}
</label>
</div>
<div class="heading">
<h6 class="mb-3 mt-3">Filter By Rating</h6>
</div>
<div class="form-check" v-for="starRating in starRatings" :key="starRating">
<input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault1"
#click="() => starAccommodations(filter)">
<label class="form-check-label area-filter-each" for="flexRadioDefault1">
{{ starRating }}
</label>
</div>
the search for area works perfectly and i have no issues. even the search bar works as good.
script
const filters = [
"All",
"Dagana",
"Lhuentse",
"Mongar",
"Pemagatshel",
"Tashiyangtse",
"Trashigang",
"Zhemgang",
];
const starRatings = [
"All",
"1",
"2",
"3",
"4",
"5",
];
export default {
name: "SidebarFilter",
props: ["filterAccommodations", "searchAccommodations" ,'filteredAccommodations','starAccommodations'],
data() {
return {
filters,
starRatings
};
},
};
these are on my components that i have build for the search filter.
and it meets with the content from another component at a parent file, which i call is model for my self reference.
Below is the Parent template
<div class="container">
<div class="row">
<div class="col-md-3 col-lg-3 col-xl-3 col-sm-12 col-xs-12">
<SidebarFilter :filterAccommodations="filterAccommodations"
:searchAccommodations="searchAccommodations"
:starAccommodations="starAccommodations"
/>
</div>
<div class="col-md-9 col-lg-9 col-xl-9 col-sm-12 col-xs-12">
<AccommodationElements :accommodations="accommodations" />
</div>
</div>
</div>
I am writing some functions to actually make the query on the json data. This is my script:
import ACCOMMODATION_DATA from '../Accommodation_DATA.json'
methods: {
filterAccommodations(filter) {
this.resetAccommodations();
if (filter === "All") {
this.accommodations = ACCOMMODATION_DATA;
} else {
this.accommodations = ACCOMMODATION_DATA.filter(accommodation => {
return accommodation.location_id.toLowerCase().includes(filter.toLowerCase());
});
}
},
starAccommodations(filter) {
this.resetAccommodations();
if (filter === "All") {
this.accommodations = ACCOMMODATION_DATA;
} else {
this.accommodations = ACCOMMODATION_DATA.filter(accommodation => {
return accommodation.star_rate.toLowerCase().includes(filter.toLowerCase());
});
}
},
searchAccommodations(search) {
this.resetAccommodations();
this.accommodations = ACCOMMODATION_DATA.filter(accommodation => {
return accommodation.title.toLowerCase().includes(search.toLowerCase());
});
},
resetAccommodations() {
this.accommodations = ACCOMMODATION_DATA;
}
}
JSON file sample:
{
"id": 100,
"title": "Onofredo Walkden",
"content": "Salivary operation NEC",
"image_id": "http://dummyimage.com/512x517.png/cc0000/ffffff",
"banner_image_id": "http://dummyimage.com/x.png/ff4444/ffffff",
"location_id": "Tashiyangtse",
"address": "9 Briar Crest Hill",
"map_lat": 40.5845053,
"map_lng": -8.0854006,
"is_featured": true,
"star_rate": 4,
"date_created": "6/22/2021",
"price": 19433.22
}
You can maybe try it like this:
<template>
<div>
{{ filterAccommodations }}
</div>
</template>
data() {
return {
title: "",
location: "",
starRate: 5,
};
},
computed: {
filterAccommodations() {
return ACCOMMODATION_DATA.filter((acc) => {
return (
acc.location_id.toLowerCase().includes(this.location.toLowerCase()) &&
acc.title.toLowerCase().includes(this.title.toLowerCase()) &&
acc.star_rate === this.starRate
);
});
},
}
In your UI you will need 3 input fields, where you can set your title, location and star rating.

How to go to an AMP page in AMP history

Hi, everybody
I have a page index.html
The source code, I took from here
I have one file story.html - AMP-story that contains 6 AMP-pages
How can I specify the path to the AMP-page in the AMP-history
I read this docs
I tried /stories/knife1/story.html/#page-1
and /stories/knife1/story/#page-1
and /stories/knife1/story.html/page-1
But it doesn't work
The first AMP-page always opens and playback continues
In my index.html, I have this code
<div class="entry-point-container">
<div class="circular-entry-point">
<div class="entry-points">
<div class="entry-point-card-container">
<img src="img/products/new/knife1/photo_2021-06-05_16-31-08.jpg" style="border-color:#FF6F32">
<span class="entry-point-card-title">Q&A with ZOE Newman</span>
</div>
<div class="entry-point-card-container">
<img src="img/products/new/knife1/photo_2021-06-05_16-39-29.jpg" style="border-color:#EF7E31">
<span class="entry-point-card-title">24 Hours in New York City</span>
</div>
<div class="entry-point-card-container">
<img src="img/products/new/knife1/photo_2021-06-05_16-39-31.jpg" style="border-color:#EF7E31">
<span class="entry-point-card-title">The Next King of the Sea</span>
</div>
<div class="entry-point-card-container">
<img src="img/products/new/knife1/photo_2021-06-05_16-40-09.jpg" style="border-color:#EF7E31">
<span class="entry-point-card-title">Spark a Passion for Reading</span>
</div>
<div class="entry-point-card-container">
<img src="img/products/new/knife1/preview1.png" style="border-color:#FF6F32">
<span class="entry-point-card-title">Spark a Passion for Reading</span>
</div>
<div class="entry-point-card-container">
<img src="img/products/new/knife1/preview2.png" style="border-color:#EF7E31">
<span class="entry-point-card-title">The Next King of the Sea</span>
</div>
</div>
</div>
</div>
{
"behavior": {
"autoplay": false,
"pageScroll": false
},
"controls": [{
"name": "close",
"position": "start"
}]
}
And I use this JS code. Maybe this is the case?
const player = document.body.querySelector("amp-story-player");
const lightboxEl = document.querySelector(".lightbox");
if (player.isReady) {
initializeCarousel();
} else {
player.addEventListener("ready", () => {
initializeCarousel();
});
}
function initializeCarousel() {
const stories = player.getStories();
const thumbnails = document.querySelectorAll(
".entry-point-card-container img"
);
console.log(thumbnails);
thumbnails.forEach((img, idx) => {
img.addEventListener("click", () => {
player.show(stories[idx].href);
player.play();
lightboxEl.classList.toggle("show");
});
});
}
player.addEventListener("amp-story-player-close", () => {
player.pause();
lightboxEl.classList.toggle("show");
});
player.show() takes as the second parameter the pageId, so you can call player.show("/stories/knife1/story.html", "page-1") and it should show the page with the ID page-1. Outside of the player, stories support the URL hashParam #page=page-1 that also loads that page.

How to render array entries in JSX using map() function with conditional wrapping

I have an array of objects in JavaScript and I want to loop through these objects and return some JSX with bootstrap classes in it such that each row always gets 2 columns displayed inside it.
options: [
{
"letter":"A",
"text": "14 March 1879"
},
{
"letter":"B",
"text": "14 March 1897"
},
{
"letter":"C",
"text": "24 May 1879"
},
{
"letter":"D",
"text": "24 June 1879"
}
]
In my experience with other languages and template engines, it is pretty simple: You just create an opening and a closing div tag with a class of row and then using your template engine, you loop through and render each object until when the counter of your loop is 2, you dynamically end that role and start a new one.
Something like this:
<div class="row">
for (var i in options) {
if(i%2 === 0) {
<!-- render object ... -->
</div><!-- then end this row -->
<div class="row"><!-- start new row -->
} else {
<!-- render object -->
}
}
</div>
I tried this method inside my map function and it was giving a syntax error because the value returned in the case where the condition passes is not valid JSX.
Thanks for any help.
Edit:
In the End, what I want to achieve is this:
If the array of objects contains 2 objects, I should be able to dynamically display it like this:
<div class="row">
<div class="col-md-6">
<div class="option correct-option">
A <!-- that is, option.letter -->
</div>
</div>
<div class="col-md-6">
<div class="option wrong-option">
B <!-- that is, option.letter -->
</div>
</div>
</div>
if the array contains 3 objects, I want to achieve this:
<div class="row">
<div class="col-md-6">
<div class="option correct-option">
A <!-- that is, option.letter -->
</div>
</div>
<div class="col-md-6">
<div class="option wrong-option">
B <!-- that is, option.letter -->
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="option correct-option">
C <!-- that is, option.letter -->
</div>
</div>
</div>
How about something like this?
{options.map((option, i) => (
i % 2 === 0 ? null : ( // skip every 2nd row
<div class="row">
A: {option}
B: {i < options.length ? options[i + 1] : null}
</div>
)
)}
You could use a regular for loop increasing i with 2 every loop, and check if the second option is set to take care of an array of uneven length:
Example
function App() {
const content = [];
for (let i = 0; i < options.length; i += 2) {
content.push(
<div class="row">
<div class="col-md-6">
<div class="option correct-option">{options[i].text}</div>
</div>
{options[i + 1] && (
<div class="col-md-6">
<div class="option correct-option">{options[i + 1].text}</div>
</div>
)}
</div>
);
}
return <div>{content}</div>;
}
HTML:
Result:
Validations:
Works with:
Array.length = 0
&
Array.length = n
You want 3 Cols?... define a const instead magic number "2"....
Code:
const options = [
{
"letter":"A",
"text": "14 March 1879"
},
{
"letter":"B",
"text": "14 March 1897"
},
{
"letter":"C",
"text": "24 May 1879"
},
];
return (
<>
{
Array.from(Array(Math.round(options.length / 2)).keys()).map((number, index) => {
return (
<div className="row">
{
options.slice(index * 2, (index * 2) + 2).map(option=>{
return (
<div className="col-md-6">
<div className={`option ${option.true ? 'correct-option' : 'wrong-option'}`}>
{option.letter}-{option.text}
</div>
</div>
);
})
}
</div>
);
})
}
</>
);

AngularJS & JSON - Obtain Value from Previous & Next Object

Background:
I have created an AngularJS test app which, obtains data from a JSON file, which is separated into categories and within each category is an employee card which is displayed through ng-repeat. These categories can then be viewed utilising a slider (using bxSlider).
Aim:
With bxSlider you can use custom Next/Previous buttons, what I wanted to achieve was to dynamically display the relevant category names in the Next/Previous buttons (please see annotation link below - my level does not allow me to post images).
Website Category Slider Wireframe
For example: the current category on view is the 'Technology' department, the previous button may then show 'Motors' department and the next button may show 'Law' department.
I understand that the code below would allow me to access the Category name 'Technology'. However this needs to be done in a dynamic nature.
{{employees[0].category}}
Below this I will include all what I believe to be relevant code.
JSON file:
[
{
"category": "Technology",
"shortname": "tech",
"icon": "fa-desktop",
"cards": [
{
"id": "card-1",
"name": "George Sofroniou",
"shortname": "G_Sof",
"age": "23",
"company": "Pirean Ltd.",
"role": "Graduate UI Developer"
},
{
"id": "card-2",
"name": "Steve Jobs",
"shortname": "S_Jobs",
"age": "56 (Died)",
"company": "Apple Inc.",
"role": "Former CEO"
},
{
"id": "card-3",
"name": "Mark Zuckerberg",
"shortname": "M_Zuck",
"age": "30",
"company": "Facebook",
"role": "CEO"
},
{
"id": "card-4",
"name": "Tim Cook",
"shortname": "T_Cook",
"age": "54",
"company": "Apple Inc.",
"role": "CEO"
},
{
"id": "card-5",
"name": "Jony Ive",
"shortname": "J_Ive",
"age": "48",
"company": "Apple Inc.",
"role": "Senior Vice President of Design"
},
{
"id": "card-6",
"name": "Marissa Mayer",
"shortname": "M_May",
"age": "39",
"company": "Yahoo!",
"role": "CEO"
},
{
"id": "card-7",
"name": "Yves Behar",
"shortname": "Y_Beh",
"age": "47",
"company": "Fuseproject",
"role": "Founder"
}
]
},
{
"category": "Motors",
"shortname": "mot",
"icon": "fa-car",
"cards": [
{
"name": "Elon Musk",
"shortname": "E_Musk",
"age": "43",
"company": "Tesla Motors",
"role": "CEO"
}
]
},
{
"category": "Football",
"shortname": "foot",
"icon": "fa-futbol-o",
"cards": [
{
"id": "card-1",
"name": "Sir Alex Ferguson",
"shortname": "A_Fer",
"age": "73",
"company": "N/A",
"role": "Retired"
}
]
},
{
"category": "Law",
"shortname": "law",
"icon": "fa-gavel",
"cards": [
{
"id": "card-1",
"name": "Harvey Specter",
"shortname": "H_Spec",
"age": "43",
"company": "Pearson Specter Litt",
"role": "Name Partner"
}
]
}
]
HTML Code:
<!-- Slider Container -->
<div class="slider-container">
<!-- Search Content -->
<!-- controls: true -->
<div class="content-results bxslider"
bx-slider="mode: 'horizontal', pager: true, nextSelector: '#next', prevSelector: '#prev', nextText: '<i class=\'fa fa-chevron-right\'></i>', prevText: '<i class=\'fa fa-chevron-left\'></i>', minSlides: 1, maxSlides:1, infiniteLoop: true, adaptiveHeight: true, hideControlOnEnd: false">
<!-- Employee -->
<div class="cards-container"
ng-repeat="item in filtered = ( employees | filter: query | orderBy:empOrder:direction )"
notify-repeat-finished>
<div class="category" ng-animate="'animate'" >
<div class="category-title">
<h1 class="title-cat"><i class="fa {{item.icon}}"></i> {{ item.category }}</h1>
</div>
<div class="category-cards-container">
<div class="employee-card card" ng-repeat="employee in filtered = (item.cards | filter: query | orderBy:empOrder:direction )" dom-manipulation>
<!-- Front Card -->
<div class="front">
<div class="pic-container">
<img ng-src="../static/images/placeholders/{{ employee.shortname }}.jpg" class="emp-pic" alt="Photo of {{ employee.name }}">
<h3 class="emp-name">{{ employee.name }}</h3>
<div class="darken"></div>
</div>
<ul class="emp-details">
<li class="detail emp-age">
<h5>Age: <small>{{ employee.age }}</small></h5>
</li>
<li class="detail emp-role">
<h5>Role: <br><small>{{ employee.role }}</small></h5>
</li>
<li class="detail emp-company">
<h5>Company: <br><small>{{ employee.company }}</small></h5>
</li>
</ul>
</div>
<!-- END Front Card -->
<!-- Back Card -->
<div class="back">
<div id="map-load">
<i class="fa fa-map-marker"></i>
</div>
<div id="maps-container">
<div id="googleMap"></div>
</div>
<i class="fa fa-times"></i>
</div>
<!-- END Back Card -->
</div>
</div>
</div>
<!-- No Matches -->
<div class="no-match" ng-show="filtered.length == 0">
<h3 class="no-matchText">Your search provides no matches!</h3>
</div>
<!-- END No Matches -->
</div>
<!-- END Employee -->
</div>
<!-- END Search Content -->
<!-- Next & Previous Buttons -->
<div class="btn-nextprev">
<div class="next-container">
<a href="" class="btn btn-next" id="next">
</a>
</div>
<div class="prev-container">
<a href="" class="btn btn-prev" id="prev">
</a>
</div>
</div>
<!-- END Next & Previous Buttons -->
</div>
<!-- END Slider Container -->
AngularJS:
Controller
var personControllers = angular.module('personControllers', ['ngAnimate']);
//PersonSearch Controller
personControllers.controller('PersonList', ['$scope', '$http',
function($scope, $http) {
$http.get('../static/scripts/data2.json').
success(function(data) {
console.log("JSON file loaded");
console.log(data);
$scope.employees = data;
//$scope.empOrder = 'name';
}).
error(function(){
console.log("JSON file NOT loaded");
});
}]);
EDIT
Updated Controller
var personControllers = angular.module('personControllers', ['ngAnimate']);
//PersonSearch Controller
personControllers.controller('PersonList', ['$scope', '$http',
function($scope, $http) {
$http.get('../static/scripts/data2.json').
success(function(data) {
console.log("JSON file loaded");
console.log(data);
$scope.employees = data;
//$scope.empOrder = 'name';
//Next & Previous Button Category Label
$scope.getNextCategoryIndex = function(currentIndex){
var nextIndex = currentIndex+1;
if( nextIndex >= $scope.employees.length ){
//move to start if at list end
nextIndex = 0;
}
return nextIndex;
}
$scope.getPrevCategoryIndex = function(currentIndex){
var prevIndex = currentIndex+1;
if( prevIndex < 0 ){
//move to the last index, if already at the start
prevIndex = $scope.employees.length - 1;
}
return prevIndex;
}
}).
error(function(){
console.log("JSON file NOT loaded");
});
}]);
Updated Next/Previous Buttons
<!-- Next & Previous Buttons -->
<div class="btn-nextprev">
<div class="next-container">
<a href="" class="btn btn-next" id="next">
{{ employees[getNextCategoryIndex($index)].category }}
</a>
</div>
<div class="prev-container">
<a href="" class="btn btn-prev" id="prev">
{{ employees[getPrevCategoryIndex($index)].category }}
</a>
</div>
</div>
<!-- END Next & Previous Buttons -->
I would probably do something like this: create functions to your controller to get the previous and next indexes (to handle the index overflows):
$scope.getNextCategoryIndex = function(currentIndex) {
var nextIndex = currentIndex+1;
if (nextIndex >= $scope.employees.length) {
// move over to start if we already were at the end of the list
nextIndex = 0;
}
return nextIndex;
}
$scope.getPrevCategoryIndex = function(currentIndex) {
var prevIndex = currentIndex+1;
if (prevIndex < 0) {
// move over to the last index, if we already are at the start
prevIndex = $scope.employees.length - 1;
}
return prevIndex;
}
And then in the HTML call those functions using $index (the current index of ng-repeat, see AngularJS documentation for ngRepeat for more details) as parameter:
<!-- Next & Previous Buttons -->
<div class="btn-nextprev">
<div class="next-container">
<a href="" class="btn btn-next" id="next">
{{employees[getNextCategoryIndex($index)].category}}
</a>
</div>
<div class="prev-container">
<a href="" class="btn btn-prev" id="prev">
{{employees[getPrevCategoryIndex($index)].category}}
</a>
</div>
</div>
<!-- END Next & Previous Buttons -->
The code you need should be:
{{employees[$index - 1].category}} //For the prev
{{employees[$index + 1].category}} //For the next
Recent Update (09-Apr-2015):
I have now been able to achieve what I wanted, on click of the button the relevant function runs and loops through the category names. One more thing to add now is that the buttons run in sync.
Controller
//Next & Previous Button Category Label
$scope.i = 0;
$scope.j = $scope.employees.length;
$scope.nextCat = $scope.i + 1;
$scope.prevCat = $scope.j - 1;
$scope.getNext = function(){
//console.log($scope.nextCat);
$scope.nextCat++;
if( $scope.nextCat >= $scope.employees.length ){
$scope.nextCat = 0;
}
$scope.prevCat++;
if( $scope.prevCat >= $scope.employees.length ){
$scope.prevCat = 0;
}
};
$scope.getPrev = function(){
//console.log($scope.nextCat);
$scope.prevCat--;
if( $scope.prevCat < 0 ){
$scope.prevCat = $scope.employees.length - 1;
}
$scope.nextCat--;
if( $scope.nextCat < 0 ){
$scope.nextCat = $scope.employees.length - 1;
}
};
HTML
<!-- Next & Previous Buttons -->
<div class="btn-nextprev">
<div class="next-container">
<a href="" class="btn btn-next" id="next"
ng-click="getNext()">
</a>
{{ employees[nextCat].category }}
</div>
<div class="prev-container">
<a href="" class="btn btn-prev" id="prev"
ng-click="getPrev()">
</a>
{{ employees[prevCat].category }}
<!-- {{ employees[prevCat].category }} -->
</div>
</div>
<!-- END Next & Previous Buttons -->
Update:
This is still not going to be a viable solution. I am technically able to achieve what is required however I am still required to use position: fixed. This means that the Category label then disappears.
I am now going to try and achieve this without it being within the ng-repeat and using ng-click it will iterate to the next Category name. Hopefully this will be the solution, and I will update upon any success/failure.
Update:
I am yet to find my optimal solution however, my current workaround for this utilises #jmustonen's solution.
Outside of the bxSlider I have the custom arrow's (if I placed these inside there were issues with the arrows not duplicating across pages - I believe there's an issue with it when it has position:fixed).
Then within my ng-repeat I include...
{{ employees[getNextCategoryIndex($index)].category }}
I will then be required to do some CSS in order for this to appear as if it is displayed as part of the Next/Previous buttons. Again these become invisible if position: fixed is used.

Passing data into foundation modals using angularjs repeater

I'm making a "members" page for a website, which has 3 columns of pictures and names for each member. I want to be able to click on the picture to get more information about that member (via Foundation's modal). I'm using a repeater to display the pictures, but I'm stuck on how to pass member data into the modal so that when I click on person A, the modal will have person A's data.
Here is what I have so far:
I store the members as a json list in members.json:
{
"current" : [
{
"name": "Bob",
"pic": "http://www.placehold.it/300x300",
"id": "blah",
"position": "position 1",
"bio": "Hi I am Bob"
},
{
"name": "Bobby",
"pic": "http://www.placehold.it/300x300",
"id": "blah",
"position": "position 2",
"bio": "Hi I am Bobby"
}
]
}
And here is my controller, uses the json file:
var app = angular.module('app').controller('memberCtrl', ['$scope', '$http', function ($scope, $http) {
'use strict';
$http.get('/data/members.json').success(function(data) {
$scope.members = data;
$scope.numColumns = 3;
$scope.current_rows = [];
$scope.current_rows.length = Math.ceil($scope.members.current.length / $scope.numColumns);
$scope.current_cols = [];
$scope.current_cols.length = $scope.numColumns;
});
}]);
And here is my html:
<!-- My attempt at the modal -->
<div ng-controller="memberCtrl" id="myModal" class="reveal-modal">
<div class="row">
<div class="large-3 columns">
<img src="http://www.placehold.it/300x300">
</div>
<div class="large-6 columns">
<center>
<!-- The following remains blank -->
<h2>{{members.current[$parent.$index * numColumns + $index].name}}</h2>
</center>
<p class="lead">Bio.</p>
<p>Hi</p>
</div>
<div class="large-3 columns">
<img src="http://www.placehold.it/300x300">
</div>
</div>
<a class="close-reveal-modal">×</a>
</div>
<!-- This creates a 3 column array of member profiles (it works) -->
<div ng-controller="memberCtrl">
<div class="row" data-ng-repeat="row in current_rows">
<div class="large-4 columns" data-ng-repeat="col in current_cols">
<img ng-src="{{members.current[$parent.$index * numColumns + $index].pic}}">
<center>
<small><h3>{{members.current[$parent.$index * numColumns + $index].name}}</h3></small>
<small><h4>{{members.current[$parent.$index * numColumns + $index].position}}</h4></small>
</center>
</div>
</div>
</div>
Add ng-click attr in the img:
<img ng-src="{{members.current[$parent.$index * numColumns + $index].pic}}"
ng-click="loadMember(members.current[$parent.$index * numColumns + $index]);"/>
And add the function in the controller:
$scope.loadMember = function (member) {
//you should be able to access the current member
console.log(member);
}
Demo on jsFiddle

Categories

Resources