Custom methods on Model Laravel and Vue - javascript

I am currently trying to implement a bookmark feature in my laravel project and i am using this design.
The Bookmark table is a pivot for User and Post table, a many to many relationship
public function BookmarkPost(Request $request,$id)
{
$book = Auth::guard('api')->user()->bookmarks()->attach($id);
return response()->json( $book);
}
/**
* Unfavorite a particular post
*
* #param Post $post
* #return Response
*/
public function unBookmarkPost(Request $request,$id)
{
$unbook = Auth::guard('api')->user()->bookmarks()->detach($id);
return response()->json( $unbook);
}
There is the code for the BookmarkController
After defining the relationship in the User Model, I created a method to check if the post has been favorited in my Post model
public function bookmarked()
{
return (bool) Bookmark::where('user_id', Auth::guard('web')->id())
->where('job_id', $this->id)
->first();
}
There is the code for the Post Model. This is supposed to check if the post was bookmared.
So i also set up a vue component that takes in two props
<bookmark-icon :id="job.id" :bookmarked="job.bookmarked ? true : false "></bookmark-icon>
So my major problem now is i am using the bookmark-icon as a child component how would i call the bookmarked() method on the Vue instance, if it were blade it would have been
{{$job->bookmarked()}}
How do i get that with Vue??

You cannot access eloquent form in vuejs.
But You can use the relationship BEFORE you pass the data to vuejs.
In order to do that you have to eager load it
(read up on it on the docs if it is new to you, very useful stuff, especially when it comes to performance)
You can read this article "Importance of eager loading "
This is how you can do it, something like this code below:
public function load_display()
{
$job = Job::bookmarked()->get();
return response()->json($job );
}

Related

Pass generic type as type parameter

I am struggling to come up with a solution to a problem i'm facing, where i am trying to use a generic type as a type parameter.
I have the following two classes/types:
UserModel.ts:
export class UserModel{
private _id : string;
public get id() : string {
return this._id;
}
public set id(v : string) {
this._id = v;
}
....
}
HttpResponse.ts:
export class HttpResponse<T>{
private _success : boolean;
public get success() : boolean {
return this._success;
}
public set success(v : boolean) {
this._success = v;
}
private _model : T;
public get model() : T {
return this._model;
}
public set model(v : T) {
this._model = v;
}
}
As you can guess, I am using this to have a generic type to handle http calls easily. The intended use is to call my http method with the HttpResponse type and whatever the expect result type is as the type parameter. For example, when making a user related http call the type parameter would be HttpResponse<UserModel>> or for a resource related call it would be HttpResponse<ResourceModel>>. However, i don't seem to be having any luck when trying this.
In my data service I have a method that POSTS to the server called 'create' and
create<T>(data: any){
//Angular's HttpClient
return this.http.post<T>(data, ...);
}
I then have a service that extends this class and overloads the create method with some extra bits before it calls super.create. I run into the issue at this point because I want to pass in HttpResponse<Type the service should return> which in the following case would be HttpResponse<UserModel>:
create<HttpResponse<UserModel>>(user: UserModel){
//stuff happens here
return super.create<HttpResponse<UserModel>>(user, ...);
}
However, this returns a syntax error at create<HttpResponse<UserModel>>.
I had a look online and found another way to achieve this as something along the lines of:
create<HttpResponse, UserModel>(user: any){
//stuff happens here
return super.create<HttpResponse<UserModel>>(user, ...);
}
But, again, this returns an error stating "HttpResponse is not generic".
The design idea is that by passing in the types in this manner, the json response from the server can be automatically mapped into the appropriate type, making it simple to use the response throughout the application
Any pointers as to where I am going wrong in my design?
A subclass has to maintain the entire interface of its base class (with some exceptions that aren't relevant here). If your data service base class contains a create method that is generic and works for every T, then your subclass cannot override create with a method that only works for T = HttpResponse<UserModel>. Instead, consider (1) defining a new method with a different name or (2) moving the T parameter from the create method to the base class itself, so that when your subclass extends the base class, it can specify the single T that it works with. (Compare to this recent question.) If this doesn't seem to be what you're looking for, then please provide more information.

Angular-js with typescript - should data be stored in controllers or services?

I develop a web api server and recently started devloping the client side also, which is developed in Angular-js and typescript.
I have something I'm not sure about regarding the design of my client side code.
Say for example that I have a view that presents list of items and this view's controller is created many times, everytime a button is clicked (for example). This view presents a list of items and therefore this array is receieved throguh Http GET in the controller each time it is created, and the view has
ng-repeat="item in vm.items"
However, it seems to me that if I save this list on a service, which from my understanding is created once per client only, I could use a single GET request once when the service is created and use it in the view like this:
ng-repeat="item in vm.service.items"
And updates to this list of items will happen through usage of signalr only.
Does the second approach has it's flaws? Because right now I can't see a reason for not doing so.
Yes, this sounds like a classic DAL-service for me. I would recommend you to work with a promise there so you are able to track when the desired data is resolved. Here is an example:
export class EntityProvider {
static serviceName: string = "entityProvider";
private entity = null;
static $inject : string[] = ["YourService", "$q"];
constructor(yourService: YourService, private mQService: ng.IQService) {
}
get getEntity(): ng.IPromise<ConnectionInfoDto[]> {
if (this.entity === null) {
return this.yourService.getEntity()
.then(result => {
this.entity = result.data;
return this.entity;
});
} else {
return this.mQService.when(this.entity);
}
}
static bootstrap(aModule: ng.IModule) {
return aModule.service(this.serviceName, EntityProvider);
}
}

Reactjs server side templates

I wonder is there a way to load a react component template from server?
When I worked with Vuejs or any other js-library I actually have to add code to a view and after it rendered by server javascript starts running and do the rest.
For instance, I can type something like this in a Symfony app to get localized string: {{ 'header.article_title'|trans }} and it were translated.
However, since templates are hardcoded into a reactjs-component I can not use php/symfony/twig functions anymore. So, I'm wondering if there a way to fetch template from a server like an AngularJS templateURL-option.
Finally get how to do what I need.
I've realized that it is possible to not have actual file by URL. So, if I need a /react/component/Article.js it could be a URL to an action.
So, I've created a new bundle, add a controller and use one action with view for a single react-component.
The skeleton code looks like this:
/**
* Class ComponentController
* #package ReactjsBundle\Controller
*
* #Route("/react/component")
*/
class ComponentController extends Controller
{
/**
* #Route("/Article.js")
*/
public function articleAction()
{
$resp = new Response();
$resp->headers->set('Content-Type', 'text/javascript');
return $this->render('ReactjsBundle:Component:article.html.twig', [], $resp);
}
}

Get current user from inside the model in Sails

I'm using toJSON() method of my model in Sails in order to control the visibility of some of it's properties, when model is exposed via application's API.
In order to decide which properties to display and which to omit I need to know the permissions of the current user. So, how do I get the current user from inside the model? Or is there a better way (pattern) to solve this problem?
Here's some sample code I want to achieve:
toJSON: function () {
var result = {};
result.firstName = this.firstName;
result.lastName = this.lastName;
// Exposing emails only to admin users.
if (currentUser.isAdmin()) {
result.email = this.email;
}
return result;
}
Your asking about reading a session inside the model call. Currently the way sails and waterline are built you can not do this.
You can use the select property on your initial model call to restrict the columns returned. Since this would be in the context of your controller you would have access to the req object.
Here are a bunch of related questions / answers on this topic.
sails.js Use session param in model
Is it possible to access a session variable directly in a Model in SailsJS
https://github.com/balderdashy/waterline/issues/556
https://github.com/balderdashy/waterline/pull/787
Sails Google Group Discussion on the topic

Ember Data not serializing record id on save(), resulting in PUT with no id?

I have a route that creates a new record like so:
App.ServicesNewRoute = Ember.Route.extend({
model : function() {
return this.store.createRecord('service');
},
setupController: function(controller, model) {
controller.set('model', model);
},
});
Then I bind that model's properties to the route's template using {{input type="text" value=model.serviceId ... }} which works great, the model gets populated as I fill up the form.
Then I save record:
App.ServicesNewController = Ember.ObjectController.extend({
actions : {
saveService : function() {
this.get('model').save(); // => POST to '/services'
}
}
});
Which works too.
Then I click the save button again, now the save method does a PUT as expected since the model has an id set (id: 102):
But then when I look at the PUT request in Dev Tools, I see that the id attribute was not serialized:
As a result, a new instance is created in the backend instead of updating the existing one.
Please ignore the serviceId property, it is just a regular string property unrelated to the record id which should be named just id.
I don't know why the id is not being serialized... I cannot define an id property on the model of course since Ember Data will not allow it, it is implicit. So I don't know what I am missing...
Any help is greatly appreciated!
The base JSONSerializer in Ember-Data only includes id in the payload when creating records. See DS.JSONAdapter.serialize docs.
The URL the RestAdapter generates for PUTting the update includes the ID in the path. In your case I believe it would be: PUT '/services/102'.
You can either extract it from the path in your backend service. Or you should be able to override the behavior of your serializer to add the id like this:
App.ServiceSerializer = DS.JSONSerializer.extend({
serialize: function(record, options) {
var json = this._super.apply(this, arguments); // Get default serialization
json.id = record.id; // tack on the id
return json;
}
});
There's plenty of additional info on serialization customization in the docs.
Hope that helps!
Initially I used ronco's answer and it worked well.
But when I looked at ember data's source code I noticed that this option is supported natively. You just need to pass the includeId option to the serializer.
Example code:
App.ApplicationSerializer = DS.RESTSerializer.extend({
serialize: function(record, options) {
options = options ? options : {}; // handle the case where options is undefined
options.includeId = true;
return this._super.apply(this, [record, options]); // Call the parent serializer
}
});
This will also handle custom primary key definitions nicely.
Well, as far as I know it's a sync issue. After first request you do the post request and then, it has been saved in the server, when you click next time the store haven't got enough time to refresh itself. I've got similar issue when I've created something and immediately after that (without any transition or actions) I've tried to delete it - the error appears, in your case there's a little bit another story but with the same source. I think the solution is to refresh state after promise resolving.

Categories

Resources