Failing to create an ajax request to handelbars.js template - javascript

I am trying to create an AJAX request (using jQuery) for handelbars.js (an by that grasp the concept of using template.
I have this data object and ajax request:
var data = { users: [
{username: { firstName: "Alan", lastName: "Johnson" } , email: "alan#test.com" },
{username: { firstName: "Allison", lastName: "House" } , email: "allison#test.com" },
{username: { firstName: "Ryan", lastName: "Carson" }, email: "ryan#test.com" }
]};
$(document).ready(function(){
$.get('h1template.js', function(template_text){
var template = Handlebars.compile(template_text);
var html = template(data);
$('#content').html(html);
});
});
this is the content of h1template.js:
<table>
<thead>
<th>Username</th>
<th>Real Name</th>
<th>Email</th>
</thead>
<tbody>
{{#users}}
<tr>
<td>{{username}}</td>
<td>{{firstName}} {{lastName}}</td>
<td>{{email}}</td>
</tr>
{{/users}}
</tbody>
</table>
Something obviously is not right because this is not working
What is wrong?
Is it something silly I do wrong with the ajax call itself? Calling it ".js" and not ".php" (for example)?
(I run the file inside my localhost and when looking on the network properties the 'h1template.js' status is 304-not-modified)

Because the template name is .js, it is being parsed as a javascript file. So you need to change it to either .html or .php or whatever you like.
Also in the users object, the username is an object, so in the template outputting {{username}} will only give you [object, object]. You need to change it to something like {{username.name}}

I played a bit with the code and found out how to write it
the h1template.html file (instead of *.js"):
<table>
...
</table>
and the script in main page is:
var data = { users: [
{username: { firstName: "Alan", lastName: "Johnson" } , email: "alan#test.com" },
{username: { firstName: "Allison", lastName: "House" } , email: "allison#test.com" },
{username: { firstName: "Ryan", lastName: "Carson" }, email: "ryan#test.com" }
]};
$(document).ready(function(){
$.get('h1template.html', function(template_text){
var source = template_text;
var template = Handlebars.compile(source);
var html = template(data);
$('#content').html(html);
});
});

Related

Trying to map elements from object of nested subarrays to a cell in an HTML table, unsure how to reach deepest sub arrays

I have a React/TypeScript component I'm building that features an HTML table for contact details.
I'm trying to map the API response to cells in the table and dynamically populate rows for each contact and their details. There are two arrays for phone numbers and addresses that are nested deep within the object and I can't figure out how to iterate over them along with the rest of the data all in one go.
I initially tried nested for loops but I hit a wall when I got to those two elements because of their position in the data object.
I then tried to use .map() in the middle of the for loops, but I hit a TypeScript error stating the element I'm trying to map over could possibly be null.
I thought about iterating over phone number and address arrays separately and then inserting them into the appropriate cells per contact but I can't figure out how to do when I'm using separate for loops to populate the other cells.
Expected Output:
Name | Member | Telephone | Email | Addresses
Ben B| Friend | 610-535-1234 | ben#gmail.com | 123 Fiction Drive,Denver
215-674-6789 234 Dreary Ln,Seattle
Alice | Family| 267-333-1234 | ally#aim.com | 437 Chance St, Pitts.
I made a CodeSandbox and dropped the current component and example data structure below. For the CodeSandbox it currently loads but as soon as you uncomment these lines you'll see the error
<td>{contacts.contactGroups[i].contacts[j].phoneNumbers}</td>
<td>{contacts.contactGroups[i].contacts[j].addresses}</td>
Current Component
import React from "react";
import { Contacts } from "./contact-types";
type Props = {
contacts: Contacts;
};
export const ContactsGrid = (props: Props) => {
const { contacts } = props;
const rows = [];
for (let i = 0; i < contacts.contactGroups.length; i++) {
rows.push(
<tr>
<td>{contacts.contactGroups[i].contactGroup}</td>
</tr>
);
for (let j = 0; j < contacts.contactGroups[i].contacts.length; j++) {
rows.push(
<tr>
<td>{contacts.contactGroups[i].contacts[j].fullName}</td>
<td>{contacts.contactGroups[i].contacts[j].member}</td>
{/* <td>{contacts.contactGroups[i].contacts[j].phoneNumbers}</td> */}
<td>{contacts.contactGroups[i].contacts[j].email}</td>
{/* <td>{contacts.contactGroups[i].contacts[j].addresses}</td> */}
</tr>
);
}
}
return (
<table>
<thead>
<tr>
<td>Name</td>
<td>Member Type</td>
<td>Telephone</td>
<td>Email</td>
<td>Address</td>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
);
};
Current Data Structure
export default {
count: 1,
contactGroups: [
{
contactGroup: "Family",
count: 1,
contacts: [
{
member: "Uncle",
fullName: "BENJAMIN BILLIARDS",
lastName: "BILLIARDS",
firstName: "BENJAMIN",
email: "shark#billiards.com",
phoneNumbers: [
{
telephoneNumber: "123-456-7899",
type: "mobile"
},
{
telephoneNumber: "610-555-7625",
type: "work"
}
],
addresses: [
{
addressLine1: "123 FAMILY ST",
addressLine2: "APT 1208",
city: "ATLANTA",
state: "GEORGIA",
zipCode: "12345"
},
{
addressLine1: "456 WORKING BLVD",
addressLine2: "",
city: "ATLANTA",
state: "GEORGIA",
zipCode: "12345"
}
]
}
]
},
{
contactGroup: "Friends",
count: 1,
contacts: [
{
member: "School Friend",
fullName: "HANS ZIMMER",
lastName: "ZIMMER",
firstName: "HANS",
email: "hans#pirates.com",
phoneNumbers: [
{
telephoneNumber: "267-455-1234",
type: "mobile"
}
],
addresses: [
{
addressLine1: "789 FRIEND ST",
addressLine2: "",
city: "SAN DIEGO",
state: "CALIFORNIA",
zipCode: "67890"
},
{
addressLine1: "234 CANARY ST",
addressLine2: "",
city: "SEATTLE",
state: "WASHINGTON",
zipCode: "67890"
}
]
}
]
}
]
};
Use a nested map:
const rows = contacts.contactGroups.map(group => <tr>
<td>{group.contactGroup}</td>
<td>
<table>
{group.contacts.map(contact => <tr>
<td>{contact.fullName}
</tr>}
</table>
</td>
</tr>;

Javascript error trying to perform a search filter using Angular JS

In my app Im trying perform a search filter on names by partial match from the beginning. Heres an example of what Im trying to do:
Lets say I have a list of names:
Ben
James
Adam
Judy
Andy
and enter the text "a" in my search field, it would return
Adam
Andy
if I further enter "an" in my search field, it would return
Andy
In my app.js, I have the code:
var myApp = angular.module("myApp", []);
myApp.controller("myController", function ($scope) {
var employees = [
{ name: "Ben", gender: "Male", salary: 55000, city: "London" },
{ name: "Jane", gender: "Female", salary: 62000, city: "Albany" },
{ name: "Rick", gender: "Male", salary: 65000, city: "Los Angeles" },
{ name: "Pam", gender: "Female", salary: 60000, city: "Paris" },
{ name: "Josh", gender: "Male", salary: 68000, city: "Brussels" },
];
$scope.employees = employees;
$scope.filtered = function (item) {
if ($scope.searchName == undefined) {
return true;
} else {
if (item.name.toLowerCase().startsWith($scope.searchName.toLowerCase()) != -1) {
return true;
}
}
return false;
}
});
And in my html page, I have the following line which displays the list of employees:
<tr ng-repeat="employee in employees | filter: filtered">
And the following line which the user inputs the search text:
<input type="text" placeholder="Search Name" ng-model="searchName.name"> <br><br>
However, when I attempt to test this, I get the error:
Error: $scope.searchName.toLowerCase is not a function. (In '$scope.searchName.toLowerCase()', '$scope.searchName.toLowerCase' is undefined)
As your ng-model is set to searchName.name, $scope.searchNameis an object, therefore it has no .toLowerCase() function.
You need to adjust your if-case like this:
if (item.name.toLowerCase().startsWith($scope.searchName.name.toLowerCase()) !== -1) {}
Furthermore, it is advisable to use identity operators instead of equality operators, unless strict identity is explicitly not needed.
The ng-model is set to searchName.name, so you may need to call on $scope.searchName.name.toLowerCase() instead of $scope.searchName.toLowerCase()

Moltin Javascript issue: moltin.Cart.Complete returns 406 not acceptable

Using the Moltin Javascript SDK and able to retrieve products and add them to my cart. However when I try to checkout the cart and process a payment I get a 406 Not acceptable returned.
This I have stripped out all my two way binding and used the code snippet from Moltin's site but still not result.
Link to the entire project as well https://github.com/humbm0/ecommerce-site.
Thanks in advance!
angular.module('ecommerceSite2App')
.controller('CheckoutCtrl', function ($scope, checkout, moltin) {
$scope.items = checkout.cart.contents;
$scope.createOrder = function() {
var order = moltin.Cart.Complete({
gateway: 'dummy',
customer: {
first_name: 'Jon',
last_name: 'Doe',
email: 'jon.doe#gmail.com'
},
bill_to: {
first_name: 'Jon',
last_name: 'Doe',
address_1: '123 Sunny Street',
address_2: 'Sunnycreek',
city: 'Sunnyvale',
county: 'California',
country: 'US',
postcode: 'CA94040',
phone: '6507123124'
},
ship_to: 'bill_to',
shipping: '1305214549095350548'
});
console.log(order);
var checkout = moltin.Checkout.Payment('purchase', order.id, {
data: {
number: '4242424242424242',
expiry_month: '02',
expiry_year: '2017',
cvv: '123'
}
});
Have you checked that you have enabled the dummy gateway from the forge dashboard? - https://forge.moltin.com/gateway
The second thing, instead of using the shipping method ID could you try using the shipping method slug instead?
If you need more help you can also request an invite to join our community slack channel where you can speak to other users and the rest of the moltin team. https://moltin.com/community

Set values to html tag from angularjs controller not working

I want to show the user profile values in HTML via an AngularJs controller, but it isn't showing in the html <p> where I bind them.
jsfiddle
AngularJs App:
var app = angular.module('myApp', []);
app.service('UserService', function () {
var userDetails = [{
id : 27,
first_name : 'Addy',
last_name : 'Villiams',
gender : 1,
email : 'addy#villiams.com',
creation_date : '2015-09-23 10:53:19.423',
age : 25,
profile_pic : 'avatar.get?uid=27'
}];
this.get = function () {
return userDetails;
}
});
app.controller('UserController', function ($scope, UserService) {
$scope.userinfo = UserService.get();
});
HTML:
<div ng-controller="UserController">
<p>{{userinfo.id}}</p>
<p>{{userinfo.first_name}}</p>
</div>
The returned object from service is an array with one object.
$scope.userinfo = UserService.get()[0]; // Get the first element from array
Demo
Or change the service to return an Object instead of array.
var userDetails = {
id: 27,
first_name: 'Addy',
last_name: 'Villiams',
gender: 1,
email: 'addy#villiams.com',
creation_date: '2015-09-23 10:53:19.423',
age: 25,
profile_pic: 'avatar.get?uid=27'
};
Demo
So your service UserService.get() returns array of objects so userinfo.id and userinfo.first_name are undefined. You can resolve it returning just object or using on view
userinfo[0].id and
userinfo[0].first_name. Please check fiddle http://jsfiddle.net/rawat/k3phygpz/533/
Remove the [] braces - you should return an object not an array:
var userDetails = {
id: 27,
first_name: 'Addy',
last_name: 'Villiams',
gender: 1,
email: 'addy#villiams.com',
creation_date: '2015-09-23 10:53:19.423',
age: 25,
profile_pic: 'avatar.get?uid=27'
};
You initialized user object in array. You can remove the square brackets [] from user initialization:
var userDetails = {
id: 27,
first_name: 'Addy',
last_name: 'Villiams',
gender: 1,
email: 'addy#villiams.com',
creation_date: '2015-09-23 10:53:19.423',
age: 25,
profile_pic: 'avatar.get?uid=27'
};
or use
$scope.userinfo = UserService.get()[0];

jquery mobile multipage with javascript template, does not always "refresh"

I have a multi-page jQuery mobile page.
When I go from Page 1 to Page 2 I see my template that I dynamically create using handlebars.
The template:
<script id="history-template" type="text/x-handlebars-template">
<div data-role="collapsible" id="share_history" >
<h3>{{share_title}}</h3>
{{#each historyItem}}
<h2>Shared with {{shared_with}}</h2>
{{#list people}}{{firstName}} {{lastName}}, {{role}}{{/list}}
{{/each}}
</div>
</script>
The javascript:
var context = {
share_title: "View Share History",
historyItem: [
{
shared_with: "with a group",
people: [
{firstName: "Bob", lastName: "Wong", role: "Dad" },
{firstName: "Tina", lastName: "Turner", role: "Guardian" },
{firstName: "Modest", lastName: "Mouse", role: "Dad" }
]
},
{
shared_with: "with 3 people",
people: [
{firstName: "Baily", lastName: "Wong", role: "Dad" },
{firstName: "Gina", lastName: "Turner", role: "Guardian" },
{firstName: "Modest", lastName: "Mouse", role: "Dad" }
]
}
]
};
var source = $("#history-template").html();
var template = Handlebars.compile(source);
Handlebars.registerHelper('list', function(people, options) {
var out = "<ul class=>";
for(var i=0, l=people.length; i<l; i++) {
out = out + "<li>" + options.fn(people[i]) + "</li>";
}
return out + "</ul>";
});
var html = template(context);
$('#share').html(html);
$.mobile.changePage('#add-edit');
When I go from Page 1 to Page 2 (in my multipage layout) it works (good).
But if I click the back button, and then go back to Page 2, I see my content...minus the additional markup jQuery mobile adds (i.e. I see content but not my jQuery mobile appearance/theme).
Edit
For my example, I had to do the following:
$('#share').html(html).trigger( "create" );
You will need to trigger the create event on the html element, e.g
el.trigger('create');

Categories