How to parse JSON with AnjularJS? - angularjs

I am trying to parse a JSON file using AngularJS like this,
<!DOCTYPE html>
<html lang="en" ng-app="tutorialApp">
<head>
<meta charset="UTF-8">
<title>App</title>
<script src="lib/angular.min.js"></script>
<script src="js/app.js"></script>
</head>
<body ng-controller="ListController">
<ul>
<li ng-repeat="item in artists">
{{item.name}}
</li>
</ul>
</body>
</html>
For some reason, the <li> tag doesn't display the JSON data.
Here's my app.js file,
var app = angular.module("tutorialApp", []);
app.controller('ListController', ['$scope', '$http', function($scope, $http) {
$http.get('js/data.json').success(function (data) {
$scope.artists = data;
});
}]);
And this is my data.json file,
{ "speakers" : [
{
"name":"Mr Bellingham",
"shortname":"Barot_Bellingham",
"reknown":"Royal Academy of Painting and Sculpture",
"bio":"Barot has just finished his final year at The Royal Academy of Painting and Sculpture, where he excelled in glass etching paintings and portraiture. Hailed as one of the most diverse artists of his generation, Barot is equally as skilled with watercolors as he is with oils, and is just as well-balanced in different subject areas. Barot's collection entitled \"The Un-Collection\" will adorn the walls of Gilbert Hall, depicting his range of skills and sensibilities - all of them, uniquely Barot, yet undeniably different"
},
{
"name":"Jonathan G. Ferrar II",
"shortname":"Jonathan_Ferrar",
"reknown":"Artist to Watch in 2012",
"bio":"The Artist to Watch in 2012 by the London Review, Johnathan has already sold one of the highest priced-commissions paid to an art student, ever on record. The piece, entitled Gratitude Resort, a work in oil and mixed media, was sold for $750,000 and Jonathan donated all the proceeds to Art for Peace, an organization that provides college art scholarships for creative children in developing nations"
},
{
"name":"Hillary Hewitt Goldwynn-Post",
"shortname":"Hillary_Goldwynn",
"reknown":"New York University",
"bio":"Hillary is a sophomore art sculpture student at New York University, and has already won all the major international prizes for new sculptors, including the Divinity Circle, the International Sculptor's Medal, and the Academy of Paris Award. Hillary's CAC exhibit features 25 abstract watercolor paintings that contain only water images including waves, deep sea, and river."
}
]}
How to display only the name objects from the JSON file? What am I missing?

Related

PayPal Donate button in React: Donate SDK or Checkout SDK integration?

The official NPM package #paypal/react-paypal-js: https://www.npmjs.com/package/#paypal/react-paypal-js only supports buttons that require client_id, I have not been able to find anything that simplifies the implementation of Donate button. PayPal provides only this HTML code below on the Donate button documentation. Please let me know if anyone has had a similar experience and how did you manage to implement it properly in React/Gatsby.
<head>
<meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Ensures optimal rendering on mobile devices. -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <!-- Optimal Internet Explorer compatibility -->
</head>
<body>
<script src="https://www.paypalobjects.com/donate/sdk/donate-sdk.js" charset="UTF-8"></script>
</body>
<body>
<div id="paypal-donate-button-container"></div>
<script>
PayPal.Donation.Button({
env: 'sandbox',
hosted_button_id: 'YOUR_SANDBOX_HOSTED_BUTTON_ID',
// business: 'YOUR_EMAIL_OR_PAYERID',
image: {
src: 'https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif',
title: 'PayPal - The safer, easier way to pay online!',
alt: 'Donate with PayPal button'
},
onComplete: function (params) {
// Your onComplete handler
},
}).render('#paypal-donate-button-container');
</script>
</body>
There are two ways to use the Donate SDK HTML/JS from react.
Configure the app to load the SDK script at page load time (typically as part of the page's <head>). The JS to render the button can then be run/outputted whenever as part of a component.
Insert the script element into the DOM after page load and once loaded render buttons with a callback function. This can all be placed in a React component's useEffect or similar. The linked example using loadAsync is for the Checkout SDK, but that's easily swapped out for Donate SDK code.
You can use the Donate SDK with a hosted_button_id as you mentioned (created at https://www.paypal.com/buttons (live) or www.sandbox.paypal.com/buttons) -- or alternatively, instead of a hosted button id just pass a business parameter with either the receiving account's PayPal email address or (ideally) its PayPal Merchant ID (since that will never change whereas an email can be removed from the account and no longer point to it)
Later edit: Note that the Donate SDK is separate from simply relabeling a normal PayPal Checkout SDK button with the text "Donate", which can be done per the react-paypal-js storybook example, as another answer mentioned. The issue with this approach is after clicking the button it will look like a standard PayPal checkout, not a donation-specific flow...
Using the actual Donate SDK instead results in a more tailored donor flow where they can select any amount in the large input, and even check an option to make their donation recurring:
I reached out to the React SDK team and they said it actually comes with support for donate out of the box and there is an example in their storybook. Here's the relevant code. If you use this approach you shouldn't need hosted_button_id:
<PayPalButtons
fundingSource="paypal"
style={{
layout: "vertical",
label: "donate"
}}
createOrder={(data, actions) => {
return actions.order
.create({
purchase_units: [{
amount: {
value: "2",
currency_code: "USD",
},
items: [{
name: "donation-example",
quantity: "1",
unit_amount: {
currency_code: "USD",
value: "2",
},
category: "DONATION",
}],
}],
})
}}
/>;
I had the same problem and I didn't see how exactly the accepted answer here could work with React because of the reference error: PayPal.Donation.Button is undefined, and the code wouldn't compile if I tried using it as a function.
I looked into appending the whole script tag as a string (dangerouslySetInnerHTML) and found this blog post to be a great explanation: Render dangerous content with React. The author makes a pretty cool use of document.Range API in order to solve the problem of executing scripts inside html. He has also published his solution as a small package: dangerously-set-html-content.
I gave it a try in my Gatsby project. First thing I'm adding the Donate SDK script tag on the body in gatsby-srr.js in order to fetch the JapaScript on page load:
exports.onRenderBody = ({setPreBodyComponents}) => {
setPreBodyComponents(
<script key={0} src="https://www.paypalobjects.com/donate/sdk/donate-sdk.js" charSet="UTF-8"/>
)
}
(I need the bizarre-looking key attribute to avoid errors when html.js is compiled. Once it's merged, the attribute is removed)
And then in the component I'm setting the script as a string:
import React from 'react'
import InnerHTML from 'dangerously-set-html-content'
const html = `
<div id="donate-button-container">
<div id="donate-button">
<script>
PayPal.Donation.Button({
...
}}).render('#donate-button')
</script>
</div>
</div>
`
function MyComponent() {
return (
<InnerHTML html={html} />
)
}
You can have a look at the GitHub repo of the package for the explanation of how useEffect and useRef hooks are used, and for some usage examples.

Creating a custom order in Angularjs for displaying filtered results by day of the week order

I'm trying to create a custom order for a page of angularjs filtered results to display a schedule of classes ordered by the day of the week. As in "Monday - class, Tuesday - class, Wednesday - class."
Right now, before filtering, the content displays in code position and after filtering, it displays by alphabetical (?) order.
The dropdown menu for "Days" also displays in alphabetical order rather than day of the week order.
My hope is to display the Days drop-down menu, the default results, and the sorted results in day of the week order.
<!-- Main Content --->
<body ng-app="app" class="container">
<div ng-controller="mainController">
<h1>Accelerate Education Sessions</h1>
<label>Track:</label>
<select class="filter" ng-model="selectedTrack" ng-options="track for track in tracks" class="form-control"> </select>
<label>Days:</label>
<select class="filter" ng-model="selectedYear" ng-options="year for year in years" class="form-control"></select>
<label>Role:</label>
<select class="filter" ng-model="selectedRole" ng-options="role for role in roles" class="form-control"></select>
<button class="filter-clear-button" ng-click="clearFilters()">Clear</button>
<table class="table">
<tbody>
<div ng-repeat="accelerate in accelerates | filter:{ track: selectedTrack, date:selectedYear, role:selectedRole}">
<div class="filter-item ed-session"><h4 class="session-title">{{ accelerate.name }}</h4>
<div class="specifics"> <b class="track-system">{{accelerate.track }}</b><br/>
Role: <b>{{accelerate.role }}</b> | Skill Level: <b>{{accelerate.skill }}</b><br/>
{{accelerate.date }} | {{accelerate.time }}</b> | {{accelerate.location }} </div>
<p class="desc"><span class="small-text">Description </span> {{accelerate.description}} — Instructor(s): <em>{{accelerate.instructors}}</em></p></div>
</div>
</tbody>
</table>
</div>
<div class="filter-form">
<ul class="filter-items" ng-repeat="accelerate in accelerates | filter:{ track:selectedTrack, date:selectedDate, name:selectedName}">
<li class="filter-item ed-session"><h4 class="session-title">{{ accelerate.name }}</h4>
<div class="specifics"> <b class="track-system">{{accelerate.track }}</b><br/>
Role: <b>{{accelerate.role }}</b> | Skill Level: <b>{{accelerate.skill }}</b><br/>
{{accelerate.date }} | {{accelerate.time }}</b> | {{accelerate.location }} </div>
<p class="desc"><span class="small-text">Description </span> {{accelerate.description}} — Instructor(s): <em>{{accelerate.instructors}}</em></p></li>
</ul>
</div>
</div>
and the JS is
(function(){
var app = angular.module("app", []);
app.controller("mainController", function($scope, accelerateData) {
$scope.accelerates = accelerateData.getAll();
$scope.roles = _.chain($scope.accelerates).pluck("role").uniq().sortBy().value();
$scope.tracks = _.chain($scope.accelerates).pluck("track").uniq().sortBy().value();
$scope.years = _.chain($scope.accelerates).pluck("date").uniq().sortBy().value();
$scope.clearFilters = function(){
$scope.selectedTrack = undefined;
$scope.selectedYear = undefined;
$scope.selectedRole = undefined;
};
});
app.factory("accelerateData", function(){
var accelerates = [
/** AMS360**/
{ track:"AMS360", name:"Words matter: Learn the Latest on eDocs, Text Setups and eForms",
role:"Administrators", skill:"Intermediate", date: 'Wednesday', time: '11:00 am - 12:00 pm', location:'Room 101', description:"We will be taking a look at eDoc delivery, connectivity, text setups and eForms. This session will be supplemented with continuing webinars offered by NetVU following conference." , instructors:'Joyce Sigler'},
{track:"AMS360", name:"All in the Family: How to Use AMS360 Data to Sort Out Acquisitions, Business Origin and Relationships",
role:"Administrators", skill:"Intermediate", date: 'Tuesday', time: '11:00 am - 12:00 pm', location:'Room 101',
description:"Releases 18r1 and 18r2 give us additional opportunities of how to classify our business, book commissions, set up relationships. This session will be supplemented with continuing webinars offered by NetVU following conference.", instructors:'Joyce Sigler'},
{track:"AMS360", name:"You Say What? Learn How to Have Data Pushed to You through Alerts, Scheduled Reports and My Agency Reports",
role:"Administrators", skill:"Intermediate", date: 'Tuesday', time: '11:00 am - 12:00 pm', location:'Room 101',
description:" Mirror, mirror on the wall, let me see the beauty of it all. Letting your data come to you. Learn about Alerts, Scheduled Reports, My Agency Reports, WorkSmart Process Dashboard and Process Analytics. This session will be supplemented with continuing webinars offered by NetVU following conference.", instructors:'Joyce Sigler'},
{
track:"AMS360", name:"Getting Cozy: Merging customers",
role:"Administrators", skill:"Intermediate", date: 'Tuesday', time: '1:00 pm - 2:00 pm', location:'Room 101',
description:" NEW with 18r2 - Let's talk about what happens when we can merge customers together. When two becomes one! This session will be supplemented with continuing webinars offered by NetVU following conference.", instructors:'Joyce Sigler'}
];
return {
getAll: function(){
return accelerates;
}
};
});
}());
This isn't a true answer, but it was a work-around that met our needs. I added the numerical date followed by a dash and then added the day of the week. Am I proud of this, no, but at least the project moved forward. If anyone knows of a true solution, please let me know!
(function(){
var app = angular.module("app", []);
app.controller("mainController", function($scope, accelerateData) {
$scope.accelerates = accelerateData.getAll();
$scope.roles = _.chain($scope.accelerates).pluck("role").uniq().sortBy().value();
$scope.tracks = _.chain($scope.accelerates).pluck("track").uniq().sortBy().value();
$scope.years = _.chain($scope.accelerates).pluck("date").uniq().sortBy().value();
$scope.clearFilters = function(){
$scope.selectedTrack = undefined;
$scope.selectedYear = undefined;
$scope.selectedRole = undefined;
};
});
/** All the Data **/
app.factory("accelerateData", function(){
var accelerates = [
{ track:"AMS360, VAP, ImageRight", name:"What's New with AMS360 and Vertafore Agency Platform", role:"All", skill:"All", date:"5/21/19 - Tuesday", time:"2:00 PM - 3:00 PM", location:"Exhibit Hall B", description:"In this session, Vertafore leaders will review the latest releases of AMS360, and give you a peek into what's next for this amazing product.", instructors:"Sharmila Ray-Vertafore, Dave Acker-Vertafore" },
{ track:"Sagitta, ImageRight", name:"What's New - Sagitta", role:"All", skill:"All", date:"5/21/19 - Tuesday", time:"2:00 PM - 3:00 PM", location:"Jr Ballroom A", description:"In this session, Vertafore leaders will review the latest releases of Sagitta and give you a peek into what's next for this amazing product.", instructors:"Bruce Westman - Sagitta Product Manager - Vertafore" },
{ track:"AIM", name:"What's New in AIM & AIM Accounting", role:"All", skill:"Beginner", date:"5/21/19 - Tuesday", time:"2:00 PM - 3:00 PM", location:"Jr Ballroom B", description:"Come and learn all that is new in AIM and AIM Accounting.", instructors:"Cameron Elisha (Vertafore), Neville Allen (Vertafore), Michele Clubb (Vertafore)" },
{ track:"QQCatalyst", name:"Welcome to Accelerate!", role:"All", skill:"All", date:"5/21/19 - Tuesday", time:"2:00 PM - 2:15 PM", location:"Jr Ballroom C", description:"Whether you're a QQCatalyst user attending Accelerate for the first time or just want an overview of the Executive Track presentations, this session will help you get the most out of your time with us and highlight important content where you can learn how to build a world-class agency.", instructors:"Rich Park-Vertafore" },
{ track:"BenefitPoint", name:"BP Product Roadmap", role:"All", skill:"All", date:"5/21/19 - Tuesday", time:"2:00 PM - 3:00 PM", location:"Jr Ballroom D", description:"Join us for a sneak peak at what Vertafore is working on right now for BenefitPoint!", instructors:"Michelle Lewis- Director Product Management-Vertafore" },
{ track:"Executive Management", name:"Leading Agency Evolution", role:"Senior Level/Executive", skill:"All", date:"5/21/19 - Tuesday", time:"2:00 PM - 3:00 PM", location:"S-232/233", description:"Steve interviews Vertafore CEO Amy Zupon on a range of topics such as her vision for agency evolution, technology investment priorities and how Vertafore is responding.", instructors:"Amy Zupon, CEO, Vertafore; Steve Anderson" },
{ track:"Carrier Focus", name:"Getting and keeping your agents producing with Sircon", role:"All", skill:"All", date:"5/21/19 - Tuesday", time:"2:00 PM - 3:00 PM", location:"S-236", description:"Getting authorized to sell doesn't have to be a hassle. Learn how Sircon connected compliance provides simple ways for agents to get in, get licensed, and get selling.", instructors:"Patrick Masi" },
{ track:"Carrier Focus", name:"MythBusters – Unlocking the mysteries of the market", role:"All", skill:"All", date:"5/21/19 - Tuesday", time:"2:00 PM - 3:00 PM", location:"S-237/238", description:"What does $120 Billion of in-force policy data reveal about market trends? What can 6 million monthly rating transactions tell us about pricing? What can the appointments and other sales credentials of 1,000 carriers tell us about industry relationships? In this session, we share some myth busting insights we've learned by digging into the data of Vertafore products.", instructors:"TBD" },
{ track:"Carrier Focus", name:"Uncover price, product, and market opportunities with RiskMatch", role:"All", skill:"All", date:"5/21/19 - Tuesday", time:"2:00 PM - 3:00 PM", location:"W-260/261", description:"With a dataset of $120B of in-force policies, RiskMatch enables Insurers to identify market trends, assess alignment of execution with underwriting appetite and to create visibility into an opportunity set of business you don’t write today. With the launch of RiskMatch Market Insights, Vertafore is providing carriers with a unique view of the market that will help you turn data into growth and efficiency.", instructors:"John Mollica" },
{ track:"QQCatalyst", name:"What's New", role:"All", skill:"All", date:"5/21/19 - Tuesday", time:"2:15 PM - 3:00 PM", location:"Jr Ballroom C", description:"We're investing in QQCatalyst . . .  come be among the first to see what we have in store for QQCatalyst this year!", instructors:"Justin Silverman-Vertafore" },
{ track:"ImageRight-AMS360/VAP-Sagitta-AIM", name:"What's New in ImageRight?", role:"Admin, End User", skill:"All", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"Exhibit Hall B", description:"The Team at Vertafore has been hard at work.  Gather around the campfire to see and hear all about the amazing new features in the latest release. Then while the fire is hot, stick around to see where the trail will take us next and provide input on which direction you would like it to go.", instructors:"Vijay Muniswamy-Sr. Product Manager-Vertafore, Steven Finch, VP Product Management, Deb Ward-Manager, Solutions Consulting" },
{ track:"AMS360/VAP", name:"Words matter: Learn the Latest on eDocs, Text Setups and eForms", role:"Administrators", skill:"Intermediate", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"Jr Ballroom A", description:"We will be taking a look at eDoc delivery, connectivity, text setups and eForms. This session will be supplemented with continuing webinars offered by NetVU following conference.", instructors:"Joyce Sigler, Geoff Lynch-Vertafore" },
{ track:"AMS360/VAP", name:"AMS360 18R1 Release: Hear from Users How They Are Using These New Features", role:"Account Manager", skill:"All", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"Jr Ballroom B", description:"Join this group discussion about how fellow users have implemented and benefited from the newest features released with 18R1.", instructors:"Angela Painter-Angela Adams Consulting, Justin Silverman-Vertafore" },
{ track:"AMS360/VAP", name:"Financial Center Overview & Accounting Tips (RJE)", role:"Accounting", skill:"Intermediate/Advanced", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"Jr Ballroom C", description:"This is where all the information flows! Come see how to keep track of unprinted checks or invoices. Check receipts that need to be deposited or Direct Bill Deposit Payments that haven't been fully processed. Cover Daily Process, track commissions, accounts current and Vendor Payables all in one place! There is so much here. Recommended for those studying for Accounting Certification.", instructors:"Janet Tuttle, Whitney Malone, Barb Wold-Vertafore" },
{ track:"AMS360/VAP", name:"What's New in Accounting", role:"Accounting", skill:"Advanced", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"Jr Ballroom D", description:"It's finally our turn! Come find out how much has been added to Accounting functionality in the 18R1 and 18R2 releases.", instructors:"Lorraine Plezia, Janice Pierson-Vertafore" },
{ track:"BenefitPoint", name:"Large Agency Round Table", role:"All", skill:"All", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"N-206", description:"What factors are at play for large agencies when it comes to BP? What are some general considerations and best practices? Get ready for some small group discussions on large agency considerations including integration with other projects like Sagitta and ImageRight, state and regional differences, national conventions, training and much more!", instructors:"Victoria Jackson - Marsh & McLennan Agency, Deb Smith- HUB, Teddy Dimulous-Vertafore" },
{ track:"BenefitPoint", name:"Small Agency Round Table", role:"All", skill:"All", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"N-207/208", description:"What factors are at play for small agencies when it comes to BenefitPoint? What are some general considerations and best practices? Get ready for some small group discussions on small agency considerations like training, system administration, using RTM, and more.", instructors:"Gary Bossert-VP Administration-Medical Mutual Group, Michael Arias-Senior Account Manager-JGS Insurance, Sharmila Ray-Vertafore" },
{ track:"Sagitta", name:"Booked and Loaded - Producer Payments", role:"Accounting;Admin", skill:"Intermediate/Advanced", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"N-209", description:"How do you track your payments to producers? Are you manually tracking your producer payments? Find out how you can utilize the Producer Payable tools in Sagitta to automate the process. We will discuss adding default commission rates for your producers as well as utilization of the pol multi functionality for out of the ordinary commission splits.", instructors:"Ed Navalany - CFO - Szerlip & Company Inc., Allyne Miller - Operations Manager - Allen Lawrence & Associates, LLC, Kim Buck - Controller - Haylor Freyer & Coon Inc., Jennifer Salvini-Vertafore" },
{ track:"Sagitta", name:"Before and After the Fire - Security/Disaster Recovery", role:"Admin", skill:"Intermediate/Advanced", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"N-210", description:"Today’s risks to our business look very different than yesterday. Have you looked at your Security Incident Response, Disaster Recovery or Business Continuity plans recently? Find out how Password Reset and Security questions and help round out your strategy and hear from other agencies how they have evolved their systems and plans to keep our most critical applications servicing clients.", instructors:"Bill Henson -Director - Customer Success Technical Manager - Vertafore, Michelle Hoffert - Director of IT - Lanier Upshaw Inc" },
{ track:"QQCatalyst", name:"Building the future - how we're revolutionizing QQCatalyst", role:"All", skill:"All", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:00 PM", location:"S-230/231", description:"Come to hear from our CEO on how QQCatalyst will lead the way in agency innovation by producing the next generation of salesroom, a full suite of APIs, commerical lines expansions, and beyond…", instructors:"Amy Zupon, CEO, Vertafore" },
{ track:"Executive Management", name:"How to Become A Top Performing Agency", role:"Senior Level/Executive", skill:"All", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"S-232/233", description:"Each year a small number of agencies earn the prestigious status of “Best Practices Agency,” and the resulting industry recognition and exclusive benefits. In this session, we’ll learn how you can achieve this level of performance by adopting Best Practice strategies developed from studying top agencies for 25 years.", instructors:"Tom Doran, Partner, Reagan Consulting" },
{ track:"Carrier Focus", name:"What can Artificial Intelligence & Machine Learning do for insurance distribution?", role:"All", skill:"", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"S-236", description:"It should come as no surprise to you that Artificial Intelligence and Machine Learning (AI/ML) are core technologies that are already transforming our industry, along with most others. What it AI/ML, and how significant a role will it play in our future? We are excited to share our thoughts on this topic, solicit your feedback on where you see AI/ML having positive impact today and discuss the best areas to  apply AI/ML to solve key problems for the insurance industry.", instructors:"Greg Ingino"
},
{ track:"Carrier Focus", name:"Sign-on Once – Implementing ID Federation (VCF)", role:"All", skill:"All", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"S-237/238", description:"A major pain point for independent agents is managing the many login credentials they use daily to do business with their carrier partners. An easy and secure solution is a top need for both agents and carriers, and Vertafore has been listening. ID Federation has come a long way to addressing these needs, and has made great strides over this past year!  We'll share the latest on how your Vertafore agents are enjoying working with federated carriers today, and what you can do to implement federation for your Vertafore agents.", instructors:"Dave Acker, Irv Kantar" },
{ track:"AIM", name:"AIM Document Designer Basics", role:"Administrator", skill:"Beginner", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"W-250", description:"This session will cover the basics of the document parameter and designer screens in order to provide foundational knowledge for creating simple to complex document templates.", instructors:"Danny Journeay (Specialty Insurance Mgrs), Kristi Newlin-Vertafore" },
{ track:"AIM", name:"Basic & Advanced AIM Accounting Security", role:"Accounting", skill:"Beginner", date:"5/21/19 - Tuesday", time:"3:15 PM - 4:15 PM", location:"W-251", description:"AIM Accounting has an enhanced security feature that allows you to establish access within each module. This session will review the default accounting security, enhanced security feature, and how to create security privileges.", instructors:"John Salmon (RT), Michele Clubb-Vertafore" },
{ track:"Executive Management-AMS360/VAP-Sagitta-QQCatalyst-ImageRight", name:"Leveraging RiskMatch:  Your own crystal ball", role:"All", skill:"All", date:"5/22/19 - Wednesday", time:"3:30 PM - 4:30 PM", location:"W-264", description:"Learn what is driving revenue gains and losses.  Visualize team work capacity.  Explore revolutionary tools that look ahead to predict revenue changes.  Use Risk Profile reports to identify white space and cross sell opportunities.", instructors:"Brent Rineck-CIO-ABD Insurance and Financial Services" },
{ track:"AMS360/VAP", name:"AMS360: Proposal Builder", role:"All", skill:"Intermediate", date:"5/23/19 - Thursday", time:"8:30 AM - 9:30 AM", location:"Exhibit Hall B", description:"Vertafore is launching the new proposal builder tool for AMS360 and Sagitta customers. This modern and intuitive tool will allow your agency to more easily pull information from your management system into professional looking and customizable templates to present to customers and prospects. Come see a demo of this feature and learn more about how to get started using it.", instructors:"Justin Silverman-Vertafore" },
{ track:"AMS360/VAP", name:"Using Data for Daily Tasks: Learn How Target Lists and Form Letters Work to Streamline Communications", role:"Administrators", skill:"Intermediate", date:"5/23/19 - Thursday", time:"8:30 AM - 9:30 AM", location:"Jr Ballroom A", description:"Let's look at the daily tasks that gibe you the ability to look at your data and let the system do the heavy lifting. This session will be supplemented with continuing webinars offered by NetVU following conference.", instructors:"Joyce Sigler, Geoff Lynch-Vertafore" },
{ track:"AMS360/VAP", name:"What's In The Batters Box: See What's Next with Renewal Tool and Expiring Source", role:"Account Manager", skill:"Basic", date:"5/23/19 - Thursday", time:"8:30 AM - 9:30 AM", location:"Jr Ballroom B", description:"A comprehensive review of the Renewal Tool and Expiring Source.", instructors:"TBA, Marti Fox, Barbara Wold-Vertafore" },
{ track:"BenefitPoint", name:"Day 3 Q & A", role:"All", skill:"All", date:"5/23/19 - Thursday", time:"11:00 AM - 12:00 PM", location:"W-263", description:"After a day of learning let's end the day with a panel discussion. Join the conversation to share what you learned, ask questions that you haven't gotten answered, and share your ideas with the development team about how you want to see BenefitPoint grow and change in the future.", instructors:"Chris Walters, Mindy Day, Michelle Lewis, Gary Bossert, Angela Minutaglio, Tony Franza" }
];
return {
getAll: function(){
return accelerates;
}
};
});
}());
html,body {
margin: 0;
padding: 20px;
font-family:Verdana, sans-serif;
}
ul,li {
padding: 0;
margin: 0;
list-style: none;
font-family:Verdana, sans-serif;
}
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.filter-form {
height: 300px;
width:100%;
}
.filter-item {
background: #fff;
min-height: 30px;
padding: 5px 10px;
color: #333;
border-bottom: solid 1px #ed601a;
width: 100%;
}
.filter-options {
display: flex;
margin-bottom: 20px;
}
.filter-option {
margin: 0 10px;
}
label, select, .filter-clear-button {
margin-left: 10px;
padding:10px;
float:left;
}
select .filter{
max-width:20%;
}
.filter-item h4{
font-weight:bold;
}
/* Education Sessions */
.ed-session {
width: 100%;
min-height: 150px;
margin: 5px;
padding:10px;
float: left;
transition: all .4s ease-in-out;
-webkit-transition: all .4s ease-in-out;
border-bottom: 2px #ed601a solid;
}
.ed-session:hover{
-ms-transform: scale(1.02); /* IE 9 */
-webkit-transform: scale(1.02); /* Safari 3-8 */
transform: scale(1.02);
/* background-color:#333;
color:#fff;
font-size:15px;*/
}
.session-title{
font-weight: 800;
font-size:18px;
margin-bottom:5px;
}
.track-system{
color:#ed601a;
}
.desc {
margin:10px 0px;
font-size: 15px;
transition: all 0.4s ease-in-out 0s;
}
.specifics{
font-size:14px;
border-left: 2px solid #ddd;
/*margin-left: 25px;*/
padding:5px;
}
.small-text{
/* font-weight:bold;*/
color:#808080;
border-right: 2px solid #ddd;
margin-right:5px;
/*background-color:#ccc;*/
}
#media (max-width: 500px) {
select{
width:100%;
float:right;
}
label{
width:100%;
margin:0px auto;
text-align:left;
}
}
}
<!DOCTYPE html>
<html>
<head>
<link type="text/css" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"/>
<script data-require="angular.js#*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<script data-require="lodash.js#*" data-semver="2.4.1" src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
<script data-require="jquery#*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script data-require="bootstrap#*" data-semver="3.1.1" src="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
</head>
<!-- Main Content --->
<body ng-app="app" class="container">
<div ng-controller="mainController">
<h1>Accelerate Education Sessions</h1>
<label>Track:</label>
<select class="filter" ng-model="selectedTrack" ng-options="track for track in tracks" class="form-control"> </select>
<label>Date:</label>
<select class="filter" ng-model="selectedYear" ng-options="year for year in years | orderBy:'date'" class="form-control"></select>
<label>Role:</label>
<select class="filter" ng-model="selectedRole" ng-options="role for role in roles" class="form-control"></select>
<button class="filter-clear-button" ng-click="clearFilters()">Clear</button>
<table class="table">
<tbody>
<div ng-repeat="accelerate in accelerates | orderBy : 'date' | filter:{ track: selectedTrack, date:selectedYear, role:selectedRole}">
<div class="filter-item ed-session"><h4 class="session-title">{{ accelerate.name }}</h4>
<div class="specifics"> <b class="track-system">{{accelerate.track }}</b><br/>
Role: <b>{{accelerate.role }}</b> | Skill Level: <b>{{accelerate.skill }}</b><br/>
Date: <b>{{accelerate.date }} </b>| {{accelerate.time }}</b> | Room:{{accelerate.location }} </div>
<p class="desc"><span class="small-text">Description </span> {{accelerate.description}} — Instructor(s): <em>{{accelerate.instructors}}</em></p></div>
</div>
</tbody>
</table>
</div>
<div class="filter-form">
<ul class="filter-items" ng-repeat="accelerate in accelerates | filter:{ track:selectedTrack, date:selectedDate, name:selectedName}">
<li class="filter-item ed-session"><h4 class="session-title">{{ accelerate.name }}</h4>
<div class="specifics"> <b class="track-system">{{accelerate.track }}</b><br/>
Role: <b>{{accelerate.role }}</b> | Skill Level: <b>{{accelerate.skill }}</b><br/>
{{accelerate.date }} | {{accelerate.time }}</b> {{accelerate.location }} </div>
<p class="desc"><span class="small-text">Description </span> {{accelerate.description}} — Instructor(s): <em>{{accelerate.instructors}}</em></p></li>
</ul>
</div>
</div>
</body>
</html>

Is it possible to filter JSON in Angular using multiple drop down menus

I have built an app for a client using my basic / beginner knowledge of Angular. It took me a lot longer than most would but it has been a great learning experience for me.
The app imports JSON data which displays products with each returned result linking to a page with more information.
The products are manually filtered i.e. I Have built pages for all possible filters (the long hard way). This is displayed as 4 initial options then you go to another page with another 4 options based off the previous option then a final page with 4 further options from here a list is returned based on the the previous selections. This way has led to a large collection of JSON files all based off the filter combinations available.
Background story aside my client now wants to be able to filter all data using drop downs on the opening page. Is this possible?
My JSON data looks like below as an example
{"Level":"student","Style":"barb","Handle":"left","ItemCode":"5.25: 606603, 5.75: 606607","title":"Jaguar Prestyle Relax Leftie","Size":"5.25, 5.75","Price":"£50.00","Description":"One micro-serrated to prevent hair bunching or slippage, these are a particularly good choice for barbers. These scissors are ergonomically designed to reduce strain on your hands and wrists, with an offset handle, finger rest and finger ring inserts for extra comfort. Made from stainless steel with a matt satin finish.","picture":"img/stubarbleft/1.jpg"}
What I would like to do is display the returned data which is not an issue I can do that part. At the top of the page I would like to have a set of dropdown filters so the top one filters the returned data but LEVEL then the second one by STYLE (keeping the level the same as selected) and third option by HANDLE (again keeping the previous options in mind)
Is this possible to do. I am out of my depth a bit but trying to learn as I go.
Thanks for your time guys
Sure, it's possible. I've prepared a self explanatory code snippet that should help you out.
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', ['$scope',
function($scope) {
$scope.model = {
selectedStyle: "",
selectedLevel: "",
filterObject: { style : "", level : ""},
recordDetails: undefined,
options: {
styles: ["", "style1", "style2"],
levels: ["", "level1", "level2"]
},
data: [{
"id": 1,
"level": "level1",
"style": "style1",
"price": 100
}, {
"id": 2,
"level": "level2",
"style": "style2",
"price": 200
}, {
"id": 3,
"level": "level1",
"style": "style2",
"price": 300
}, {
"id": 4,
"level": "level2",
"style": "style1",
"price": 400
}]
};
$scope.showDetails = function (record) {
$scope.model.recordDetails = record;
}
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<select name="styleSelect" id="styleSelect" ng-options="option for option in model.options.styles" ng-model="model.filterObject.style"></select>
<select name="levelSelect" id="levelSelect" ng-options="option for option in model.options.levels" ng-model="model.filterObject.level"></select>
Current filter object: {{model.filterObject}}
<div ng-repeat="record in model.data | filter:model.filterObject">
<a href="#" ng-click="showDetails(record)">
<ul>
<li>{{record.id}}</li>
<li>{{record.level}}</li>
<li>{{record.style}}</li>
</ul>
</a>
</div>
<div>
Record details:
{{model.recordDetails}}
</div>
</div>
Please let me know whether anything needs further explanation.

Marionette nested composite view

Can I use nested composite view to make the output like this?
Nike
Football, Basketball
Reebok
Football, Basketball, Running
I did write nested composite view in this way. I'm not sure is there any other better way or best practice way to implement this.
Structure:
BrandCompositeView
itemView: Layout1
#brand<-BrandView (Nike, Reebok)
#sport<-SportCompositView
itemView: SportView
BrandCompositeView (generate Nike, Reebok),
itemView of BrandCompositeView is a layout1 with div id are(#brand, #sport)
SportCompositView (generate Football, Basketball, Running)
itemView of SportCompositView is SportView
BrandView and SportView are itemView
Layout1 is Marionette.Layout
inside Layout1.js
initialize:function(){
this.brandView = new BrandView({"model": this.model});
this.sportView = new SportCompositView({"collection":collection});
}
onRender: function () {
this.brand.show(this.brandView);
this.sport.show(this.sportView);
}
Yes it's possible.
Approach I have used for tree structures - article.
How about if I want to make this (collection with more than 1 child?)
Car: [
{
Car1
name: car1
image: [{img1}, {img2}, {img3}]
comment: [{comment1}, {comment2}, {comment3}]
price: $1000
},
{
Car2
name: car1
image: [{img1}, {img2}, {img3}]
comment: [{comment1}, {comment2}, {comment3}]
price: $2000
}
]
<script id="car-template" type="text/template">
<li><%= name %></li>
<div id="photo-container"></div>
<li><%= price %></li>
<div id="comment-container"></div>
</script>
I actually just wrote an answer that might help you a couple days ago. Check out this thread - Construct views for data nested several levels deep
Basically it has you use backbone relational to automatically handle all of your nesting. Then you can just abstract off of that for your composite view inside of your composite view.

Resolving object dependencies on client using Restangular

I have problems with restoring my entity relations at the (AngularJS) client after retrieving them via REST using Restangular. I searched a lot, but could not find a clean solution. I have some years of programming experience, but I'm quite new to the AngularJS ecosphere and the REST paradigm.
The task
At my Spring Data backend I have two entities, Article and ArticleGroup, in a 1:n relationship. The resulting REST json (via Spring Data Rest) looks like this:
Article
{
"_embedded": {
"articles": [
{
"id": 1,
"name": "A Drink",
"price": 2.90,
"created": null,
"modified": null,
"active": false,
"displayOrder": 0,
"_links": {
"self": {
"href": "http://localhost:8080/articles/1"
},
"articleGroup": {
"href": "http://localhost:8080/articles/1/articleGroup"
}
}
},
...
ArticleGroup
{
"_embedded": {
"articleGroups": [
{
"id": 1,
"name": "Drinks",
"printer": null,
"_links": {
"self": {
"href": "http://localhost:8080/articleGroups/1"
},
"articles": {
"href": "http://localhost:8080/articleGroups/1/articles"
}
}
},
...
Now I want to display a tabgroup containing the articleGroup.name as the tab's label and a table of the articles in this articleGroup as its content:
<tabset>
<tab ng-repeat="group in articleGroups" heading="{{group.name}}">
<table class="table">
<tr ng-repeat="article in group.articles">
<td ng-click="increase(article)">{{article.name}}</td>
<td>{{article.price | currency }}</td>
...
</tr>
</table>
</tab>
</tabset>
I retrieve the articleGroups easily in my AngularJS controller using Restangular:
Restangular.all('articleGroups').getList()
.then(function(groups) {
$scope.articleGroups = groups;
});
This works fine and the tabs show up nicely. Now I can do so for the articles as well, but here I come upon the problem which I'm dealing with for days now.
The problem
How can I filter the articles for their articleGroup so every portion of articles appears in the right tab? What is the right expression in the ng-repeat above where I just put "group.articles" as a placeholder now?
This sounds very easy, but my problem is that I have no operational identification of an Article's articleGroup to filter the right articles in the ng-repeat for each tab. What I tried:
using the self.href as an id à la article._links.articleGroup.href == articleGroup._links.self.href, but this doesn't work as you can see in the JSON above those two links are set up differently
adding (database) ids to the JSON, but of course an article does not contain the id of its articleGroup, but only the link relation
looping through articleGroups and retrieving each group's articles into an array with the articleGroup.id as the key, but I can't get this to work out as I either get undefined errors by JavaScript or infinite loops
Help
Before I continue fiddling along for hours, it would be great if you could give me hints on which direction to take and what a "clean" and methodologically sound approach to the task would be. How can I bring articles and their corresponding group back togehter?
It seems like such an easy (and frequent) problem, but I tried for hours and days to get it running and fear I'm missing something. I looked at many examples but none of them helped me to have a breakthrough.
I'm happy to provide any further information as needed. Thanks a lot in advance!
Well, I solved it. It turned out that I got lost in the handling of asynchronous requests, especially between having a data object itself and a promise for a request, i.e. placeholders which provide access to the data as soon as it is available - very well explained in this post.
Restangular always returns promises. So I came up with the following solution which works exactly as I wanted to:
For the controller code:
Restangular.all('articleGroups').getList()
.then(function(groups) {
$scope.articleGroups = groups;
for(i=0;i<groups.length;i++) {
$scope.articles[groups[i].id] = groups[i].getList("articles")
}
});
So when the articleGroups arrive from the server, I walk through all of them and put them into the array $scope.articles with the articleGroup.id as key. Notice that group[i].getList("articles") returns a promise for the articles relation. With Restangular's $object property, I receive the articles data array in the ng-repeat:
<tabset>
<tab ng-repeat="group in articleGroups" heading="{{group.name}}">
<table class="table">
<tr ng-repeat="article in articles[group.id].$object | orderBy:'id':false ">
<td>{{article.name}}</td>
<td>{{article.price | currency }}</td>
</tr>
</table>
</tab>
</tabset>
Now, all articles of the selected articleGroup's tab are displayed on the tab. While this seems fine, I'm still not sure if this is the best solution in terms of style or performance. But at least it's a step ahead. Comments very welcome.

Resources