Accessing Image Arrays via JSON with AngularJS - javascript

UPDATE:
I can now do what I wanted to do, sort of. I can click on the thumb and the large image will display in the lighbox. A second a tag with the same data-lightbox name uses another ng-repeat as etee suggested.
As you can see from the code it is not perfect and I would still like to do it properly. I alos managed to use a nested forEach to get to the 'large' array in the JSON file, and they show in the console.log but I don't know how to get them from there to the original lighbox so it displays the set, and you'll see the current way shows the same image twice.
Here is some of the JSON file:
[
{
"name":"Cedar Run",
"album_name":"CedarRun",
"img":[
{
"thumb":["cedarRun.jpg", "cedarRun.jpg","cedarRun.jpg"]
},
{
"large":["IMG_6001.jpg","IMG_6009.jpg"]
}
],
"cabin_id":"17",
"sleeps":"2",
"description":"1 Room",
"number_of_bedrooms":"1",
"bedrooms":
{
"bedroom1":"1 Queen",
"bedroom2":"",
"bedroom3":"",
"bedroom4":""
},
"pull_out":"",
"living_room":"",
"bathrooms":"",
"bathroom_info":"Bath with Tub/Shower",
"other_info":"",
"winter_info":"Winter RR Only",
"winter_rate":"198.90",
"summer_info":"Summer RR Only",
"summer_rate":"198.90",
"cabin_description":"Quaint cabin perfect for two. A unique location with a view of the horseback rides going by throughout the day. Also has one small dorm refrigerator and working fireplace with firewood supplied by the ranch."
},
{
"name":"Pioneer",
"album_name":"Pioneer",
"img":[
{
"thumb": ["pioneer.jpg"]
},
{
"large":["IMG_8561.jpg","IMG_8567.jpg", "IMG_8568.jpg"]
}
],
"cabin_id":"25",
"sleeps":"2",
"description":"1 Room",
"number_of_bedrooms":"1",
"bedrooms":
{
"bedroom1":"1 Queen",
"bedroom2":"",
"bedroom3":"",
"bedroom4":""
},
"pull_out":"",
"living_room":"",
"bathrooms":"",
"bathroom_info":"Bath with Tub/Shower",
"other_info":"",
"winter_info":"Winter RR Only",
"winter_rate":"198.90",
"summer_info":"Summer RR Only",
"summer_rate":"198.90",
"cabin_description":"One cozy cabin built in the log style with country charm in mind. Located along the hillside of the sledding hill overlooking the ranch. Also has one small dorm refrigerator and working fireplace with firewood supplied by the ranch."
}
]
The AngularJS
<table class="table table-hover">
<tr ng-repeat="x in cabins | filter:search:true">
<td>
<div>
<a data-lightbox="{{x.name}}" data-title="{{x.name}}" href="_img/_lodging/{{x.album_name}}/1200w/{{x.img[1].large[0]}}">
<img class="cabin-thumb-main" ng-src="_img/_lodging/cabin_tn/{{x.img[0].thumb[0]}}">
</a>
<a ng-repeat="y in x.img[1].large" data-lightbox="{{x.name}}" data-title="{{x.name}}" href="_img/_lodging/{{x.album_name}}/1200w/{{y}}" ></a>
<td>
<h3><strong>{{x.name}}</strong></h3>
<span>{{x.description}}</span><span><small> (Sleeps {{x.sleeps}})</small></span>
<h4>{{x.other_info}}</h4>
<br>
<h4>Description</h4>
<p>{{x.cabin_description}} </p>
<h5>Bed & Bath</h5>
<p>{{x.bedrooms.bedroom1}}</p>
<p>{{x.bedrooms.bedroom2}}</p>
<p>{{x.bedrooms.bedroom3}}</p>
<p>{{x.bedrooms.bedroom4}}</p>
<p>{{x.pull_out}}</p>
<p>{{x.bathroom_info}}</p>
<br>
</tr>
</table>
The call using ng-app
$scope.search = {};
$http.get('_js/lodging.json').then(function (response) {
$scope.cabins = response.data;
$scope.images = []
angular.forEach($scope.cabins, function(item){
angular.forEach(item.img, function(i){
var large_img = i.large;
// return large_img;
console.log(large_img);
})
})
});
Link to Test Page

<div ng-repeat="img in x.img[1].large">
<p>{{img}}</p>
</div>
Try this and here is the working plunker
Now since you have fetched the images you can add them to ng-src.

Related

Javascript template literals - retrieve subcollection sets

I have data I need to integrate in a string using Template literals. I'm managining to do it except for when the data is of the type Collection.set.
My data is made of a table called Company with multiple records. I need to loop inside it to retrieve the data for each company( this bit is OK and already works), but then inside each company one of the attribute/column called company_tags is of type Collection.set So i need to loop (sort of loop inside the loop) to retrieve the data in order to inject it inside a Template literal, and this part I am failing to do it.
Javascript code
var html = "";
result.forEach(function(msg) {
console.log(msg);
console.log(msg.company_tags);
msg.company_tags.forEach(function(value) {
console.log(value);
});
html += `
<tr id="company-1234" data-id="1234">
<td class="name">
<h2>This is the company name ${msg.company_name}</h2> for which they agree to send an email to ${msg.company_email}
<td class="location">
<h3> ${msg.company_location_city}</h3>
</td>
<td class="tags">
<h2>yhis is one of the company tags: <b>${msg.company_tags[i]} </b> and it looks nice</h2>
</td>
</tr>
`;
});
document.getElementById("target").innerHTML = html;
Of course above the part <h2>This are the company tags: ${msg.company_tags[i]} does not work.
I made several attempts I show further below at reaching this Collection set but failed.
The global data called "msg" in the code above comes from a third party. To show you the structure of the data I need to parse/loop/retrieve look like here are the results of the console.log you see on the code above:
The data is the following: this is one of the Company record shown by the console.log in the code above:
console.log(msg) outputs
c {createdAt: Wed Jul 04 2018 16:49:56 GMT+0200 (CEST), updatedAt: Mon Jul 09 2018 15:26:25 GMT+0200 (CEST), _metadata: d}
company_email: "companyemail1#example.com"
company_name: "example name"
company_location : "Dublin"
company_tags: Set(3)
updatedAt: and so on...
d {_isLocked: false, _readyPromise: Promise, _deferred: null, _root: c, _state: 0, …}
console.log(msg.company_tags) outputs something I am not sure to fully understand. Seems like what is called Collection set.
Set(3) {"tag1", "improvement", "sexy"}
size : 3
__persistedSize__ : 3
__persistedState__:
{tag1: "tag1", improvement: "improvement", sexy: "sexy"}
__proto__ : Set
[[Entries]] : Array(3)
> 0 : "tag1"
> 1 : "improvement"
> 2: "sexy"
length : 3
Today when I my javascript code (see above) operates, I manage to have in my html the right data shown for the columns of "string "type. So the part below works fine for me:
<h2>This is the company name ${msg.company_name}</h2> for which they agree to send an email to ${msg.company_email}
BUT the part below with the column of type Collection.set does not work and shows "undefined"
<td class="tags">
<h2>This is one of the company tags: ${msg.company_tags[i]}
</td>
It's like I need to loop again (inside the other loopForEach).
Some attempts that failed:
var html = "";
result.forEach(function(msg) {
html += `
<tr id="company-67851" data-id="67851">
<td class="name">
<h2>This is the company name ${msg.company_name}</h2> for which they agree to send an email to ${msg.company_email}
<td class="location">
<h3> ${msg.company_location_city}</h3>
</td>
<td class="tags">
<h2>This is one of the company tags: <b>${ msg.company_tags.forEach(function(value) {
<h2>value</h2>
</div>
</a>
});
} </h2> and it looks nice
</td>
</tr>
`;
});
document.getElementById("target").innerHTML = html;
I also tried
${ msg.company_tags.forEach( (k, v) => `<h2>${v}</h2>`).join(" ") }
and also
${msg.company_tags.map(company_tag => <h2>This is one of the company tags: ${company_tag}</h2> and it looks nice`).join('')}
but I'm always getting UNDEFINED error or even sometimes
Uncaught (in promise): TypeError: .map is not a function
Nothing has been working so far. It's a little over my head as a javascript rookie.
My goals is that for example I see in the html for the example of record I gave above:
<td class="tags">
<h2>This is one of the company tags: <b>tag1</b> and it looks nice</h2>
<h2>These are the company tags: <b>imrovement</b> and it looks nice</h2>
<h2>These are the company tags: <b>sexy</b> and it looks nice</h2>
</td>
Seems like you need to convert msg.company_tags set into array:
var company_tags = []
msg.company_tags.forEach((k,v) => company_tags.push(v))
Then you should be able to map not forEach over it, as only map returns from function, forEach is used for side effects.
Also you can fetch generating of company tags into separate function.
${company_tags.map(company_tag => `<h2>This is one of the company tags: ${company_tag}</h2> and it looks nice`).join('')}

Limit angular ng-repeat to certain rows

For example if i had the json dataset here of all languages of books:
$scope.data = [{
"title": "Alice in wonderland",
"author": "Lewis Carroll",
"lang": ["en"]
}, {
"title": "Journey to the West",
"author": "Wu Cheng'en",
"lang": ["ch"]
}]
And I simply wanted to display exclusively english books, would I be able to do this purely using a filter in ng-repeat?
E.g.
<div ng-repeat="d in data | filter:d.lang='en'" style="margin-bottom: 2%">
{{d.title}}
</div>
I do not want to do it via any sort of form control (radio button etc). Would this be possible?
-EDIT- Thanks #GrizzlyMcBear for leading me down the right path! I got it to work with a slightly different filter function (which I'll paste below)
app.filter('MyFilter', function() {
var out = [];
angular.forEach(input, function(i) {
if (i.lang[0] === 'en') {
out.push(i);
}
})
return out;
}
});
and in the HTML
<div ng-repeat="d in data | MyFilter" style="margin-bottom: 2%">
{{d.title}}
</div>
Try like this
<div ng-repeat="d in data | filter: { lang : 'en'} " style="margin-bottom: 2%">
DEMO
You should use angular's filter,
I would also suggest that you use a function in the filter:
<div ng-repeat="item in collection | filter:filteringFunction" style="margin-bottom: 2%">
{{d.title}}
</div>
This way gives you more freeeeeedom (you're more than welcome to shout it Mel Gibson style ;-) )
in filtering your data by introducing more complex filtering logic.
var filteredLang = "en";
function filterByBookLanguage(collectionItem) {
var result = false;
if (collectionItem.lang[0] === filteredLang) {
result = true;
}
return result;
}
$scope.filteringFunction = filterByBookLanguage;
Now If you wish, you can also change the comperator function - filterByBookLanguage
(my terminology).
Say that your boss suddenly wants you to change the filtering logic from filtering books
into filtering by the author's name. Now all you have to do is add this condition:
if (bossWantsToChangeFilter) {
$scope.filteringFunction = filterByAuthorName;
} else {
$scope.filteringFunction = filterByBookLanguage;
}
All you have to remember is to write the comperator function with the current filtered item
as an argument and update the compared value of the language/author name
in the location you've found convenient ($scope, local variable, service etc.).

How to handle array in angular js/HTML

I'm using a Web API to display values in HTML via Angular.
I have 4 attributes: Id, MovieName, Date and Cast. Cast is an array. I don't know how to handle the Cast attribute.
Controller.js
app.controller('MyController', function ($scope, MyService) {
$scope.getemploy = function () {
var promise = MyService.getMovies();
promise.then(function (pl) {
$scope.Movies= pl.data
},
function (error) {
$log.error('Some Prob', error);
});
}
GetMovies()--> will bring movie details(Cast attribute will have male, female lead names in the array).
HTML File :
<tr ng-repeat="mov in Movies">
<td>{{mov.Id}}</td>
<td>{{mov.MovieName}}</td>
<td>{{mov.Date}}</td>
<td>{{mov.Cast}}</td>
</tr>
But it's not working. I think I'll need some other way to handle Cast attributes, whether in html or angular.
My Json output for your reference:
[
{
"_movieId": 1,
"_moviename": "Olympus Has Fallen",
"_releaseDate": 2013,
"_cast": [
"Gerard Butler",
"Dylan McDermott",
"Aaron Eckhart",
"Angela Bassett"
]
}
Can anyone please help?
But its not working....
Because according to posted JSON your receive, HTML should be with different keys. Try this:
<tr ng-repeat="mov in Movies">
<td>{{mov._movieId}}</td>
<td>{{mov._moviename}}</td>
<td>{{mov._releaseDate}}</td>
<td>{{mov._cast.join(', ')}}</td>
</tr>
I used simple join method of array to render comma separated list of actors. If you need something more specific, you will need to make use of one more ngRepeat on mov._cast array (see Danny's answer).
I'm not sure what you mean by the Cast is not working, but I'm guessing it's just showing the JSON object in the HTML? You could show all the cast members in a list doing something like:
<tr ng-repeat="mov in Movies">
<td>{{mov.Id}}</td>
<td>{{mov.MovieName}}</td>
<td>{{mov.Date}}</td>
<td>
<ul>
<li ng-repeat="member in mov.Cast">{{ member }}</li>
</ul>
</td>
</tr>

orderBy in ng-repeat

JS:
$scope.termexamlist = {
0:{
0id:"1",
1name:"Doe, John",
2term1:"89"
},
1:{
0id:"2",
1name:"Aayt, Ray",
2term1:"90"
}
};
HTML:
<tr ng-repeat="t in termexamlist">
<td ng-repeat="(key,value) in t">{{value}}</td>
</tr>
i got this ng-repeat code which generates list of students with their term exam grades, i want to sort it by 1name but it didnt work i use to put <tr ng-repeat="t in termexamlist | orderBy:'1name' "> but it didnt work. i tried different codings too but it didnt work either. Sorry im just a beginner in angularjs programming. Thanks for the help :D
You should not have put identifiers when you declared your array
$scope.termexamlist = [
{
0id:"1",
1name:"Doe, John",
2term1:"89"
},
{
0id:"2",
1name:"Aayt, Ray",
2term1:"90"
}
];
This will be enough and enable you to iterate through it and ordering it.
Also, it's strange the way you prefix your variables, but that's none of my business
$scope.termexamlist = [
{
0id:"1",
1name:"Doe, John",
2term1:"89"
},
{
0id:"2",
1name:"Aayt, Ray",
2term1:"90"
}
];
remove 0 and 1 in your data , it will work fine
i got it now, i add underscore to the key of the object so it will look like this $scope.termexamlist={0:{_0id:"1",_1name:"Doe, John",_2term1:"89"}}. i retain the number coz chrome sort the returned data of json_encode

Change content of a div based on an array within an array

Pastebin of index.html: http://pastebin.com/kdKFqTxe
Just copy and paste that and run it (this works but with some broken img links & no css).
With regards to the pastebin, just click on a node, and then click the first broken image below the video. What should happen is a dialogue box should appear with links to articles (from tubeArray). All relevant code is pasted below.
I'm trying to dynamically change the contents of a div when I click an image. The image has it's respective id (the first index in the inner array) within the first inner array there's another array (index 3). I want to populate my div (id="articleLinks") with those links using JQuery when the image is clicked.
JavaScript & JQuery:
The tube array. *Note: the first index of each element in tubeArray is the ID & the news articles aren't linked to anything particular. Only interested in tubeArray[0] & tubeArray[4]
var tubeArray = [
['UQ', -27.495134, 153.013502, "http://www.youtube.com/embed/uZ2SWWDt8Wg",
[
["example.com", "Brisbane students protest university fee hikes"],
["example.com", "Angry protests over UQ student union election"],
]
],
['New York', 40.715520, -74.002036, "http://www.youtube.com/embed/JG0wmXyi-Mw",
[
["example.com" , "NY taxpayers’ risky Wall Street bet: Why the comptroller race matters"]
]
],
['To The Skies', 47.09399, 15.40548, "http://www.youtube.com/embed/tfEjTgUmeWw",
[
["example.com","Battle for Kobane intensifies as Islamic State uses car bombs, Syrian fighters execute captives"],
["example.com","Jihadists take heavy losses in battle for Syria's Kobane"]
]
],
['Fallujah', 33.101509, 44.047308, "http://www.youtube.com/embed/V2EOMzZsTrE",
[
["example.com","Video captures family cat saving California boy from dog attack"],
["example.com","Fines of £20,000 for dogs that chase the postman"]
]
]
];
A for loop which goes through each element in tubeArray then assigns id to the first index. Also an image that calls the function myFunctionId which takes the parameter this.id.
for (i = 0; i < tubeArray.length; i++) {
var id = tubeArray[i][0];
//other code
'<img src="img.png" onclick="myFunctionId(this.id);" id="' + id + '">' +
//other code
}
function myFunctionId (id) {
journal = id;
alert(journal) //just a test
//I want to search through tubeArray with the id and find the matching inner array.
//I then want to loop through the innerArray and append to my html a link using JQuery.
$('#articleLinks').append("<a href='"+innerArray[0]+"'>"+innerArray[1]+'</a>'); // use CSS to break lines
}
}
HTML:
<div id="articleLinks">
Example Link<br>
</div>
Any help would be greatly appreciated. I've tried to simplify & cut out as much as I can so it's readable.
try this...
function myFunctionId (id) {
console.log(tubeArray);
tubeArray.forEach(function(entry) {
if (entry[0]==id) {
entry[4].forEach(function(innerArray){
$('#articleLinks').append("<a href='"+innerArray[0]+"'>"+innerArray[1]+'</a>'); // use CSS to break lines
});
return;
}
});
}
it makes it look like this for me... you're gonna have to handle that encoding issue. with the apostrophe. there are a lot of ways to handle it...
so.... if it was me... which it's not. but if it was... i would use an associative array instead of a numerically indexed one because it's easier to read the code and understand what you're using and where and how and things and stuff.
tubeArray = {
'UQ' : { 'location': [-27.495134, 153.013502],
'youtube': "example.com/embed/uZ2SWWDt8Wg",
'articles': [["example.com/queensland/brisbane-students-protest-university-fee-hikes-20140521-zrk8o.html", "Brisbane students protest university fee hikes"],
["example.com/content/2012/s3578878.htm", "Angry protests over UQ student union election"], ]
},
'New York': { 'location': [0.715520, -74.002036],
'youtube': "example.com/embed/JG0wmXyi-Mw",
'articles': [["example.com/2014/10/19/ny-taxpayers-risky-wall-street-bet-why-the-comptroller-race-matters/" , "NY taxpayers’ risky Wall Street bet: Why the comptroller race matters"]],
},
}

Categories

Resources