I have an html file and a JS file. The JS file contains some data that I want to present in the html file depending on a clicked link from another html file
html file:
<div class="jumbotron mb-5">
{{product.name}}
</div>
<div class="jumbotron mb-5">
{{product.price}}
</div>
<div class="jumbotron mb-5">
{{product.description}}
</div>
js file
var app = angular.module('app', [']);
app.controller('prodCtrl', function ($scope) {
$scope.courses = [
{
id: 1,
name: 'prod 1',
description: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid ea fugit
tempore error, tenetur adipisci hic voluptas sapiente distinctio,.',
price: 100,
image: 'public/photos/prod1.png'
},
{
id: 2,
name: 'prod 2',
description: 'Lorem ipsum dolor sit amet consectetur adipisicing elit.',
price: 30,
image: 'public/photos/prod2.png'
},
];
});
in another html page I have the products listed as links and I want to present them in the html page up there depending on the link I clicked
You would pass the param in the route with ui-router
It sounds like you're asking for dynamic routing. There are a few questions about this on SO, but to point you in the right direction for what you're doing:
You have to declare your routes in the app config like so:
angular.module('myApp', [
'ui.router'
])
.config(function($stateProvider) {
$stateProvider
.state({
name: 'product',
url: '/product/{id}', //{id} or :id will tell it to expect the param
templateUrl: '/products/index.html',
controller: 'ProdCtrl'
});
});
Inside your index.html file, make sure you add:
<div ng-app="myApp">
<ui-view></ui-view>
</div>
(or where you want the content to appear)
And finally, your controller:
.controller('ProdCtrl', function($scope, $stateParams) {
//get id from the url and convert it to an int to match data type in courses id
//may want to consider doing some validation
$scope.productId = parseInt($stateParams.id);
var courses = [
{
id: 1,
name: 'prod 1',
description: 'Lorem ipsum dolor sit amet consectetur adipisicing elit.',
price: 100,
image: 'public/photos/prod1.png'
},
{
id: 2,
name: 'prod 2',
description: 'Lorem ipsum dolor sit amet consectetur adipisicing elit.',
price: 30,
image: 'public/photos/prod2.png'
}
];
//find the matching item by id and set it to scope
$scope.product = courses.map(function(item) {
if (item.id === $scope.productId) {
return item;
}
});
});
You should now be able to go to /product/1 and see prod 1
Please note this is untested code, but should get you on the right track. I also renamed a couple things for clarity and be more aligned with common practices (e.g. myApp and ProdCtrl).
If you go through the ui-router documentation, you can also achieve this without using the id in the url and have it pass params in the background. This would mean you can only access that page via links in your app and not deep link them.
I creating a web app using express-generator using handlebar as templating engine. If I display array of object from response, it displays. But, when I each loop in view display nothing.
/********************************
model file ../controllers/books.js
*********************************/
var request = require('request');
exports.list = function(req, res, next){
request.get({ url: "https://jsonplaceholder.typicode.com/posts" }, function(error, response, body) {
if (!error && response.statusCode == 200) {
res.render('index', { title: 'speed Tracker', list: body });
}
});
};
/***********************
route file
************************/
var express = require('express');
var router = express.Router();
var books = require('../controllers/books');
/* GET home page. */
router.get('/', books.list);
<!-- language: lang-html -->
<table id="datatable" class="table table-striped table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Album Id</th>
<th>title</th>
<th>url</th>
<th>image</th>
</tr>
</thead>
{{list}}
<tbody>
{{#each list}}
<tr>
<td>{{id}}</td>
<td>{{userId}}</td>
<td>{{title}}</td>
<td>{{body}}</td>
<td></td>
</tr>
{{/each}}
</tbody>
</table>
json of list
[
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
},
{
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
},
{.....
I have added code above data is not display in each loop.
I have to convert list from String to Object in book.js file. I have add the code below.
var request = require('request');
exports.list = function(req, res, next){
request.get({ url: "https://jsonplaceholder.typicode.com/posts" }, function(error, response, body) {
if (!error && response.statusCode == 200) {
res.render('index', { title: 'speed Tracker', list: JSON.parse(body) }); // add JSON.parse to convert string to object :)
}
});
};
I am having difficulty accessing model data with underscore, nothing is appearing on screen and I'm not getting any errors. Any help would be greatly appreciated.
Here is my templating area
<script type='text/template' id='ListContainerView'>
<p> <%= ListItemModel.id %> </p>
<p> <%= ListItemModel.network %> </p>
<p> <%= ListItemModel.created_by_id %> </p>
</script>
Collection
var ListItemCollection = Backbone.Collection.extend({
baseUrl: '/api/get_accounts',
url: '/api/get_accounts',
model: ListItemModel,
total: 0,
// Sample data
TESTDATA: {"status":"ok","posts":[{"id":"1","schedule":"2020-0417 17:00:00","utc_offset":"420","project_id":"1","network":"facebook","network_name":"TestFacebookPage","network_thumb":"https://scontent.xx.fbcdn.net/v/t1.0-9/17634406_1854330461448271_6787736791983791423_n.jpg?oh=e4c3a3573c0fc59359422cfd66a3865a&oe=598721E7","message":"Test Post 1 (just text, approved)","data":[],"customer_approved":"1","manager_approved":"1","rejection_message":"","created_at":"2020-0413 17:41:03","created_by":"admin","created_by_id":"1","created_by_name":"John Admin"},{"id":"2","schedule":"2020-0419 19:00:00","project_id":"1","network":"facebook","network_name":"TestFacebookPage","network_thumb":"https://scontent.xx.fbcdn.net/v/t1.0-9/17634406_1854330461448271_6787736791983791423_n.jpg?oh=e4c3a3573c0fc59359422cfd66a3865a&oe=598721E7","message":"Test Post 2 (text with image, approved) Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.","data":{"pictures":["https://pbs.twimg.com/media/C9T6n0UUwAAOBaU.jpg"],"image_added":"true","picture":"https://pbs.twimg.com/media/C9T6n0UUwAAOBaU.jpg","type":"photo"},"customer_approved":"1","manager_approved":"1","rejection_message":"","rejection_message_manager":"","created_at":"2020-0413 17:42:34","created_by":"admin","created_by_id":"1","created_by_name":"John Admin"},{"id":"3","schedule":"2020-0421 22:00:00","network":"facebook","network_name":"TestFacebookPage","network_thumb":"https://scontent.xx.fbcdn.net/v/t1.0-9/17634406_1854330461448271_6787736791983791423_n.jpg?oh=e4c3a3573c0fc59359422cfd66a3865a&oe=598721E7","message":"Test Post 3 (link, approved) http://www.adultswim.com/videos/rick-and-morty/","data":{"image_added":"true","pictures":["http://i.cdn.turner.com/adultswim/big/img/2015/07/17/Rick%26MortyS02_fbsearchTn.jpg"],"picture":"http://i.cdn.turner.com/adultswim/big/img/2015/07/17/Rick%26MortyS02_fbsearchTn.jpg","link":"http://www.adultswim.com/videos/rick-and-morty/","name":"Watch Rick and Morty on Adult Swim","caption":"www.adultswim.com","description":"Every episode of Rick and Morty is now on AdultSwim.com for free. Rick is a mad scientist who drags his grandson, Morty, on crazy sci-fi adventures. Their escapades often have potentially harmful consequences for their family and the rest of the world. Join Rick and Morty on AdultSwim.com as they trek through alternate dimensions, explore alien planets, and terrorize Jerry, Beth, and Summer.","domain":"www.adultswim.com","type":"link"},"customer_approved":"1","manager_approved":"1","rejection_message":"","created_at":"2020-0413 17:43:29","created_by":"admin","created_by_id":"1","created_by_name":"John Admin"},{"id":"4","schedule":"2020-0424 17:00:00","network":"facebook","network_name":"TestFacebookPage","network_thumb":"https://scontent.xx.fbcdn.net/v/t1.0-9/17634406_1854330461448271_6787736791983791423_n.jpg?oh=e4c3a3573c0fc59359422cfd66a3865a&oe=598721E7","message":"Test Post 4 (text, pending)","data":[],"customer_approved":"0","manager_approved":"1","rejection_message":"","created_at":"2020-0413 17:43:48","created_by":"admin","created_by_id":"1","created_by_name":"John Admin"},{"id":"5","schedule":"2020-0426 19:00:00","network":"facebook","network_name":"TestFacebookPage","network_thumb":"https://scontent.xx.fbcdn.net/v/t1.0-9/17634406_1854330461448271_6787736791983791423_n.jpg?oh=e4c3a3573c0fc59359422cfd66a3865a&oe=598721E7","message":"Test Post 5 (picture, pending)","data":[],"customer_approved":"0","manager_approved":"1","rejection_message":"","created_at":"2020-0413 17:44:03","created_by":"admin","created_by_id":"1","created_by_name":"John Admin"},{"id":"6","schedule":"2020-0428 21:00:00","network":"facebook","network_name":"TestFacebookPage","network_thumb":"https://scontent.xx.fbcdn.net/v/t1.0-9/17634406_1854330461448271_6787736791983791423_n.jpg?oh=e4c3a3573c0fc59359422cfd66a3865a&oe=598721E7","message":"Test Post 6 (link, pending) https://www.reddit.com/","data":{"image_added":"true","pictures":["https://b.thumbs.redditmedia.com/2Hwaff37fC4f37j-3orrbjVAOVBChqbdm_dXeIhjlNw.jpg"],"picture":"https://b.thumbs.redditmedia.com/2Hwaff37fC4f37j-3orrbjVAOVBChqbdm_dXeIhjlNw.jpg","link":"https://www.reddit.com/","name":"reddit: the front page of the internet","caption":"www.reddit.com","description":"reddit: the front page of the internet","domain":"www.reddit.com","type":"link"},"customer_approved":"0","manager_approved":"1","rejection_message":"","created_at":"2020-0413 17:44:19","created_by":"admin","created_by_id":"1","created_by_name":"John Admin"}],"total":"6"},
initialize: function(models, options) {
this.total = this.TESTDATA.total;
this.reset(this.TESTDATA.posts);
}
})
Views...
var ListContainerView = SOCIView.extend({
template: _.template($('#ListContainerView').text()),
className: 'ListContainerView'
})
var SOCIView = Backbone.View.extend({
render: function() {
if (typeof this.beforeRender === 'function') {
this.beforeRender();
}
var modelData = { };
if (this.model && this.model instanceof Backbone.Model) {
modelData = this.model.toJSON();
}
if (typeof this.template === 'function') {
this.$el.html(this.template(modelData));
}
if (typeof this.afterRender === 'function') {
this.afterRender();
}
return this;
}
})
and script inside HTML...
<script type="text/javascript">
$(document).ready(function() {
// Instantiate and render Backbone view
$('.home_body').append( new ListContainerView({
collection: new ListItemCollection(),
}).render().el)
});
</script>
The toJSON method on a Backbone model gives you a simple copy of the model attributes. In your case, this:
modelData = this.model.toJSON();
should give you an object that looks like this:
{
id: 1,
schedule: "2020-0417 17:00:00",
utc_offset: "420",
...
}
Notice that there is no ListItemModel anywhere in that object. That object would be suitable for a template that looks like this:
<p> <%= id %> </p>
<p> <%= network %> </p>
<p> <%= created_by_id %> </p>
If you really wanted the ListItemModel prefixes in the template then you'd want to say:
this.template({ ListItemModel: modelData })
when calling the template function.
Alternatively you could compile the template using the {variable: 'ListItemModel'} option to _.template and leave the template and this.template call alone. So your view would have:
template: _.template($('#ListContainerView').html(), { variable: 'ListItemModel'),
and the rest wouldn't change.
Where you define your template for the ListContainerView, I think using .text() (instead of .html()) might be causing your problem. Instead try
template: _.template($('#ListContainerView').html())
and see if it works.
Jquery's .text() ignores html markup like <span> or <strong> tags (etc), so it may be removing your templating tags <% ... %> as well, giving you just a few spaces.
i have written some code to open and close all tabs of an accordion respectively use a separate 'open' and 'close' button. How ever it requires me to dynamically add a key value pair(a Boolean value) to my json data.
What is the best practice in this situation? should i add the Boolean value as a static json element or is it OK to dynamically add values when their sole purpose is for visual structure and not relevant to actual object data.
HTML/Angular directives
<div id="app" ng-app="demoApp">
<div id="controller" ng-controller="demoAppCtrl">
<uib-accordion close-others="false">
<div class="btn-group form-group">
<button type="button" class="btn btn-warning" ng-click="toggle(true)">Open</button>
<button type="button" class="btn btn-warning" ng-click="toggle(false)">Close</button>
</div>
<uib-accordion-group is-open="hero.state" ng-click="setOpened(false)" ng-repeat="hero in heroes">
<uib-accordion-heading>
{{hero.name}}
</uib-accordion-heading>
{{hero.bio}}
</uib-accordion-group>
</uib-accordion>
</div>
</div>
Javascript/Angular
var app = angular.module('demoApp', ['ngAnimate','ui.bootstrap']);
app.controller('demoAppCtrl', function($scope) {
// This json object contain only one entry as an example
$scope.heroes = [
{'name': 'Captain America', 'team': 'Avengers', 'bio': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vitae metus placerat, condimentum nisl et, accumsan sapien. Quisque molestie magna nulla, id malesuada sem interdum a.'}
];
$scope.addDefaultState = function(val) {
for (var i=0;i<$scope.heroes.length;i++) {
$scope.heroes[i].state = val;
}
}
$scope.addDefaultState(false);
$scope.toggle = function(status) {
$scope.heroes.forEach(function(e) {
e.state = status;
});
}
});
codepen.io - Working example (with corrections)
In my opinion the static json should not contain Boolean state value. It is okay to dynamically add values for visual presentation.
In your code the function addDefaultState is not needed. The is-open="hero.state" will take care of default state cause initially it will not find state and will consider it as false. So you change your code like below it should work too:
var app = angular.module('demoApp', ['ngAnimate','ui.bootstrap']);
app.controller('demoAppCtrl', function($scope) {
// This json object contain only one entry as an example
$scope.heroes = [
{'name': 'Captain America', 'team': 'Avengers', 'bio': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vitae metus placerat, condimentum nisl et, accumsan sapien.'}
];
$scope.toggle = function(status) {
$scope.heroes.forEach(function(e) {
e.state = status;
});
}
});
I have a Q&A JSON feed with the following:
"questions": [
{
"answer": "Ea et non sunt dolore nulla commodo esse laborum ipsum minim non.",
"id": 0,
"poster": "Chelsea Vang",
"question": "Ex ex elit cupidatat ullamco labore quis cupidatat. Reprehenderit occaecat mollit ex proident aliqua. Anim minim in labore pariatur adipisicing velit dolore elit nostrud proident reprehenderit in voluptate.",
"userAsked": false
},
{
"answer": null,
"id": 1,
"poster": "Serena Randolph",
"question": "Esse occaecat anim cupidatat eu sit ad eiusmod. Et tempor deserunt ea ipsum velit irure elit qui. Ipsum qui labore laboris Lorem occaecat enim Lorem exercitation ut non duis. Sit cillum incididunt culpa ipsum.",
"userAsked": true
}
]
I want to create a custom filter that allows you to filter (by select dropdown) the results by: All Questions, "userAsked: true" a.k.a My Questions, and Answered Questions (so questions that are not 'null' in this case it would be something like !null?). I know how to create a custom filter for a single object, but can't figure out how to do it in this instance since I am trying to filter by more then one option-I can't do an ng-repeat for the select options because of this.. unless I am under the wrong impression.
My view looks something like this:
<select>
<option value="all">All Questions</option>
<option value="answered">Answered Questions</option>
<option value="mine">My Questions</option>
</select>
<ul class="list-unstyled">
<li ng-repeat="questions in qa.questions">
<strong>Question:</strong><br>
{{questions.question}}<br>
<strong>Answer:</strong><br>
{{questions.answer}}
<hr>
</li>
</ul>
Controller:
sessionControllers.controller('SessionDetailCtrl', ['$scope', '$routeParams', 'SessionFactory', 'CommentsFactory', 'QAFactory', function($scope, $routeParams, SessionFactory, CommentsFactory, QAFactory){
$scope.session = SessionFactory.get({id: $routeParams.id});
$scope.comments = CommentsFactory.get({eventId: $routeParams.id});
$scope.qa = QAFactory.get({eventId: $routeParams.id});
}]);
Please help! Thank you :)
I was able to figure it out by implementing some of what #tymeJV suggested.
View
<select ng-model="filterItem.question" ng-options="item.questionType for item in filterOptions.questions">
<option value="All Questions">All Questions</option>
<option value="Answered Questions">Answered Questions</option>
<option value="My Questions">My Questions</option>
</select>
<ul>
<li ng-repeat="questions in qa.questions | filter: myCustomFilter">
<strong>Question:</strong>
<br>{{questions.question}}<br>
<strong>Answer:</strong><br>
{{questions.answer}}
</li>
</ul>
Controller
$scope.filterOptions = {
questions: [
{questionType: 'All Questions'},
{questionType: 'Answered Questions'},
{questionType: 'My Questions'}
]
};
//Mapped to the model to filter
$scope.filterItem = {
question: $scope.filterOptions.questions[0]
};
//Custom filter - filter based on the QuestionType selected
$scope.myCustomFilter = function (data) {
if ($scope.filterItem.question.questionType === "All Questions") {
return true;
} else if ($scope.filterItem.question.questionType === 'Answered Questions') {
return data.answer != null;
} else if ($scope.filterItem.question.questionType === 'My Questions') {
return data.userAsked;
}
};
Hmm, attach a model to your select filter and try something like this:
<select ng-model="questionFilter">
<option value="all">All Questions</option>
<option value="answered">Answered Questions</option>
<option value="mine">My Questions</option>
</select>
<li ng-repeat="questions in qa.questions | filter: myCustomFilter">
And the controller:
$scope.myCustomFilter = function(item) {
if (questionFilter == "all") {
return true;
} else if (questionFilter == "answered") {
return item.answer != null;
} else if (questionFilter == "mine")
return item.userAsked;
}