How to dynamically add routes to angularjs from database - node.js

I am creating an NodeJs + AngularJS Application. I have list of Hotels stored into database. I want to create dynamic route based on the hotel name and the load partial view based on property ID.
E.g In my database I have:
HotelID HotelName
1 example hotel
2 second example hotel
3 third example hotel
In app.js I want something like this
var hotelierApp = angular.module('hotelierApp', ['ngRoute', 'ngCookies', 'pascalprecht.translate', 'hotelierApp.services', 'hotelierApp.directives', 'hotelierApp.filters', 'hotelierApp.controller']);
hotelierApp.run(function ($rootScope) {
$rootScope.langId = 1;
})
hotelierApp.config(['$routeProvider', '$locationProvider', '$translateProvider',
function ($routeProvider, $locationProvider, $translateProvider) {
angular.forEach(hotels, function (hotel) {
$routeProvider.when(hotel.name.replace(" ","-"), { templateUrl: 'partials/property', controller: propertyCtrl });
});
angular.forEach(reviews, function (review) {
$routeProvider.when(review.title.replace(" ","-"), { templateUrl: 'partials/review', controller: reviewCtrl });
});
$locationProvider.html5Mode(true);
$translateProvider.useStaticFilesLoader({
prefix: 'data/locale-',
suffix: '.json'
});
$translateProvider.preferredLanguage('en');
$translateProvider.useLocalStorage();
}
]);
Here Hotels/reviews will be the list coming from database by making api calls and also I want to pass their corresponding Ids as route params to the controller.
I have many other section in my application for which i have to create routes from database.
Please help.
Regards,
- Manoj

There is no reason you need to do that.
i'm pretty sure your routes can be factored into something like
$routeProvider.when("/:id/:name", {
templateUrl: 'partials/property', controller: propertyCtrl })
then use $routeParams to get name of the hotel in your controller.As for template urls,your can pass a function instead of a string that will resolve the name of the template you need to use.
templateUrl:function(pathParms){...}
So no need to use angular.forEach.

While this is using another router: http://dotjem.github.io/angular-routing/ the same stuff is possible in tne core router.
Here is illustrated what #mpm is saying you can do: http://plnkr.co/edit/8XuJswpx0FucwMczWTHF?p=preview
In your case I think Option1 would be most appropriate, this is because you talk about a generated url pr. hotel, which makes me assume that there is a large similarity in layout for all hotels.
When that is the case, they may as well share template, where you can just populate the template with the hotel specific data.

Related

Create custom API with strapi

I've a content type called continent. Which we the name suggests contains all the information about each continents. Strapi already created API endpoints for me like
continents/:id
But I want to search the continent by it's name since the general user won't be able to search by id
I've created the endpoint
continents/:continent_name
I've also created custom controller following documentation
const { sanitizeEntity } =
requiree('strapi-utils');
module.exports = {
async findOne(ctx) {
const { continent_name } = ctx.params;
const entity = await
strapi.services.continent.findOne({
continent_name
});
return sanitizeEntity(entity, { model:
continents });
And also exposed the API to public
But doesn't seem to anything
Just returns error
How am I supposed to do it
For your use case, you don't need to extend the model controller. You can just pass the continent name as a query param . For example, your url could be something like base_url/continent?continent_name=Asia.
For the code mentioned in the question, there is an issue, the model name should be strapi.models.continent and not continents. Also in the first line requiree('strapi-utils'), you have an extra e in the require. I am assuming that was just a typo.

How to send some data of one template to another template Meteor

I want to share some data from template to another template using Meteor. I have a template i.e allInventory.html on which i am showing some data in table form i added three links there that is. one for view , edit and delete what i want iam getting all the data from backend into one of helper i.e productDetails and i bind an event with view button that will take the data of current user clicked on which product so i have successfully getting the data at my allinventory template but there is another template i.e productDetails on which i want to render or show that data. But stuck with that i have data on allInventory click event but not know how do ishare the same with productDetails template.
Here is my allInventory.js
Template.allInventory.rendered = function() {
Template.allInventory.events({
"click .btn":function (e){
data = $(e.target).attr('data');
Router.go('productDetail', {data: $(e.target).attr('data')}, {query: 'q=s', hash: 'hashFrag'});
console.log("button clicked.."+data);
console.log(data);
}
})
ProductDetails.js
Template.productDetail.rendered = function () {
Template.productDetail.helpers({
productDetails: function() {
return data;
}
});
allInvenrtory.html
<button type="button" data ="{{productInfo}}" class="btn btn-info btn-sm"><i class="fa fa-eye"></i>View</button>
I just simply want to share allInventory template data with productsDetails template.
Any help would be appriciated!
Thanks
I'd recommend avoiding Session for this purpose, since it is a global object, but more importantly, because there are better ways to do it.
You can pass data from the parent templates to the child template using helpers: https://guide.meteor.com/blaze.html#passing-template-content
You can pass data from the child to the parent templates using callbacks https://guide.meteor.com/blaze.html#pass-callbacks
I'd structure this app to have a container (page) template, which will have all the subscriptions and render one of your templates based on the URL.
You can use the Session variable if you want to share data between templates.
You can follow this guide:
http://meteortips.com/first-meteor-tutorial/sessions/
I would put both template in a third, parent template.
ParentTemplate
-SharedInfo
-KidTemplate1
-KidTemplate2
Then having this third template hold the information you want to share across templates.
For that you can use a ReactiveVar, ensuring that change by template1 code on the parent template is visible in template2 as well.
To access the parent template for the kids, you can do something along those lines :
Blaze.TemplateInstance.prototype.parentTemplate = function (levels) {
var view = Blaze.currentView;
if (typeof levels === "undefined") {
levels = 1;
}
while (view) {
if (view.name.substring(0, 9) === "Template." && !(levels--)) {
return view.templateInstance();
}
view = view.parentView;
}
};

Laravel Slugs with Str::slug

Looking at Str::slug for my frontend URL generation but just wondering how you guys go about implementing it with routes etc, for example, how would you guys go about changing http://www.example.com/courses/1 to http://www.example.com/courses/this-course
OK, I did it this way:
// I have a slug field in my courses table and a slug field in my categories table, along with a category_id field in my courses table.
// Route
Route::get('courses/{categorySlug}/{slug?}', function($categorySlug, $slug) {
$course = Course::leftJoin('categories', 'categories.id', 'courses.category_id')
->where('categories.slug', $categorySlug)
->where('courses.slug', $slug)
->firstOrFail();
return View::make('courses.show')->with('course', $course);
});
Works like a charm. It gets the $categorySlug and $slug variables then uses them to filter the Eloquent model Course to get the correct course object from the database.
EDIT: You can generate a URL in your view like:
http://www.example.com/courses/it-training/mcse
By doing something like:
{{ $course->title }}
A have a method in my Category like below that retrieves the parent category slug. This could be better achieved though using some sort of presenter class which would allow you to simply use $course->url but I haven't got around to doing this yet. I will update the answer when I do.
public function parentCategorySlug($parentId)
{
if ($parentId === '0')
{
return $this->slug;
}
return $this->where('id', $parentId)->first()->slug;
}
You can use the cvierbrock's Eloquent-Sluggable package.
As for me I created a helper function and used the following method taken from here.
public static function getSlug($title, $model) {
$slug = Str::slug($title);
$slugCount = count( $model->whereRaw("url REGEXP '^{$slug}(-[0-9]*)?$'")->get() );
return ($slugCount > 0) ? "{$slug}-{$slugCount}" : $slug;
}
You can create a related model Slug, and approach the course in your methods like so:
$course = Slug::where('slug', $slug) -> firstOrFail() -> course;
I have also implemented a similar URL mapping but I preferred to have both the ID and the slug in the requested URL, like this:
http://www.example.com/courses/1/my-laravel-course
This method allows me to get the requested course object from the ID given in the URL, rather than having to store the slugs in my DB table.
Route::post('courses/(:num)/(:any)', function ($courseid, $slug) {
$course = Course::where('id', '=', $courseid)->get();
return View::make('courses.show')->with('course', $course);
}
For Laravel 8:
Given my URL:
http://www.example.com/courses/this-course
My route:
Route::get('/courses/{course:slug}' , function(Course $course){
return view('showCourse' , [
'course' => $course
])
})

The right pattern for returning pagination data with the ember-data RESTAdapter?

I'm displaying a list of articles in a page that are fetched using the Ember Data RESTAdapter. I need to implement a bootstrap'esque paginator (see: http://twitter.github.com/bootstrap/components.html#pagination) and cant seem to find a sane pattern for returning pagination data such as, page count, article count, current page, within a single request.
For example, I'd like the API to return something like:
{
articles: [{...}, {...}],
page: 3,
article_count: 4525,
per_page: 20
}
One idea was to add an App.Paginator DS.Model so the response could look like:
{
articles: [{...}, {...}],
paginator: {
page: 3,
article_count: 4525,
per_page: 20
}
}
But this seems like overkill to hack together for something so trivial. Has anyone solved this problem or found a particular pattern they like? Is there a simple way to manage the RESTAdapter mappings to account for scenarios such as this?
Try to use Ember Pagination Support Mixin and provide your own implementation of the following method. Instead of loading all the content, you can fetch the required content when the user is navigating the pages. All what you need initially is the total account of your records.
didRequestRange: function(rangeStart, rangeStop) {
var content = this.get('fullContent').slice(rangeStart, rangeStop);
this.replace(0, this.get('length'), content);
}
With ember-data-beta3 you can pass a meta-property in your result. The default RESTSerializer looks for that property and stores it.
You can access the meta-data like this:
var meta = this.get("store").metadataFor("post");
If you are not able to change the JSON returned from the server you could override the extractMeta-hook on the ApplicationSerializer (or any other Model-specific serializer).
App.ApplicationSerializer = DS.RESTSerializer.extend({
extractMeta: function(store, type, payload) {
if (payload && payload.total) {
store.metaForType(type, { total: payload.total }); // sets the metadata for "post"
delete payload.total; // keeps ember data from trying to parse "total" as a record
}
}
});
Read more about meta-data here

Converting Backbone's Todo List example from localStorage

I have been looking at the Todo list example (source) for Backbone.js. The code uses local storage, and I wanted to try and convert it so that it operated via a RESTful webservice.
Suppose the webservice already exists at the route todos/. I figured I need to add in a url piece into Backbone.Model.extend and remove the localStorage: new Store("todos") line when we perform Backbone.collection.extend.
window.Todo = Backbone.Model.extend({
url : function() {
return 'todos/'+this.id;
}
// Default attributes for a todo item.
defaults: function() {
return {
done: false,
order: Todos.nextOrder()
};
},
// Toggle the `done` state of this todo item.
toggle: function() {
this.save({done: !this.get("done")});
}
});
What is the proper way to do this?
Url should be set in Collection, if you have need for diferent urls than those created by collection than declare url in model.
You need to remove
<script src="../backbone-localstorage.js"></script>
from index.html since it is linked after backbone.js and effectively overrides Backbone's sync method to store in localStorage.
I would leave the model as it is in the Todos example. In the collection class add this property:
window.TodoList = Backbone.Collection.extend({
...
url: '/todos',
...
}
Calling fetch() on the collection should retrieve a list of Todo objects.
If you are using Rails you need to set ActiveRecord::Base.include_root_in_json = false otherwise Backbone.js will not be able to pull out the Todo objects from the returned json.

Resources