ng:areq fn is not a function got objectService angularjs es6 - angularjs

I have 1 service which extends other. When I try to import it in controller got this error ng:areq fn is not a function got UserRepository. I think my problem is in right way injecting this service. Here is my Service:
import { USER_REPO_CONFIG } from '../repository.config';
import { AbstractRepository } from '../abstract.repository';
import { UserModel } from './user.model';
import 'rxjs/add/operator/map';
class UserRepository extends AbstractRepository {
constructor($http) {
'NgInject'
super($http, USER_REPO_CONFIG, UserModel);
}
/**
* Gets the user by ID
*
* #param {number} userId - ID of a user to find
* #returns {Observable<UserModel>} - User model instance
*/
getUser(userId) {
return this.getItem(userId);
}
/**
* Creates the user
*
* #param {UserModel} user - User model instance
* #returns {Observable<UserModel>} - User model instance observable
*/
createUser(user) {
return this.createItem(user);
}
/**
* Updates the user
*
* #param {number} userId - ID of a user to update
* #param {UserModel} user - User model instance
* #returns {Observable<UserModel>} - User model instance observable
*/
updateUser(userId, user) {
return this.updateItem(userId, user);
}
}
export { UserRepository };
here is my Module:
import { HelloComponent } from './hello/hello.component';
import { UserRepository } from '../core/repository/user/user.repository';
const greetingModule = angular
.module('app.greeting',[])
.component('helloComponent', new HelloComponent)
.service('UserRepository', new UserRepository)
.name;
export { greetingModule };
and my Controller:
import { UserRepository } from '../../core/repository/user/user.repository';
class HelloController {
constructor(UserRepository) {
this.hello = 'Hello World';
this.service = UserRepository;
}
getAll() {
console.log('user Repository', this.service)
}
}
HelloController.$inject = ['UserRepository'];
export { HelloController };

.service('UserRepository', new UserRepository)
.service() expects a function, you pass an object. You can pass the class directly:
.service('UserRepository', UserRepository)
Passing the class effectively passes the constructor function.

Related

Laravel 5.8 and React Native using pusher: error listening to private channel: No callbacks on conversations34 for pusher:subscription_succeeded

The problem is when the app developer tries to listen to the event via pusher private channel. Here's the laravel code.
routes/api.php
Route::middleware('auth:api')->post('/broadcast/auth', 'Api\Auth\BroadcastAuthController#auth');
routs/channels.php:
// notifications channel
Broadcast::channel('users.{id}', function ($user, $id) {
return (int)$user->id === (int)$id;
});
// conversations channel
Broadcast::channel('conversations.{conversation}', function ($user, \App\Models\Conversation
$conversation) {
return $conversation->users->contains($user);
});
MessageSent event
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($message)
{
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('conversations.' . $this->message->conversation_id);
}
/**
* Load user relation.
*
* #return array
*/
public function broadcastWith()
{
return [
'message' => $this->message->load('user')
];
}
}
React receiving the message
var Echotest= new Echo({
broadcaster: 'pusher',
key: 'xxxxxxxxxxx',
forceTLS: true,
cluster:"eu",
authEndpoint: 'https://example.com/api/broadcast/auth' ,
auth: {
headers: {
Authorization: "Bearer " + token ,
}
}
});
console.log(Echotest);
Echotest.channel("conversations" + this.state.conversation_id)
.listen("App\Events\MessageSent", e => {
alert(e)
});
But the result is:
Pusher : Event sent : {"event":"pusher:subscribe","data":{"channel":"conversations34"}}
Pusher : Event recd :
{"event":"pusher_internal:subscription_succeeded","channel":"conversations34","data":{}}
Pusher : No callbacks on conversations34 for pusher:subscription_succeeded
Is there anything else need to be done in Laravel to make it work in react? or the issue in react and need to be fixed? Please advise and thanks in advance.
Just Change the "Echotest.channel" to "Echotest.private"

Laravel Lighthouse, how can i get all array data when i do subscription?

I do subscription with laravel + Lighthouse + Laravel WebSockets + vue-apollo tech.
When i subscription, i wanna get all array data, but i only got changed data.
My schema.graphql is below.
type Mutation {
updateTest(id: ID!, name: String, result: Int): Test #update
#broadcast(subscription: "testSub")
}
type Subscription {
testSub(id: ID): Test
}
type Test {
id: ID!
name: String
result: Int
}
This is my vue-apollo code
const subQuery = gql`subscription testSub($id: ID) {
testSub(id:$id) {
id
name
}
}`
const observer = this.$apollo.subscribe({
query: subQuery,
variables () {
return {
id: 14,
}
},
})
observer.subscribe({
next (data) {
console.log('subscribe')
console.log(data)
},
error (error) {
console.log('err')
console.error(error)
},
})
When i do mutation like below.
mutation {
updateTest(id:14, name: "hahaha", result:1) {
id
name
}
}
vue-apollo get subscription like pic.
I recognized return is only changed value instead of all data.
So i change subscription schema like below.
type Subscription {
testSub: [Test] #all
}
I also changed vue-apollo code.
const subQuery = gql`subscription testSub { #delete argument
testSub { #delete argument
id
name
}
}`
const observer = this.$apollo.subscribe({
query: subQuery,
variables () {
return {
id: 14,
}
},
})
observer.subscribe({
next (data) {
console.log('subscribe')
console.log(data)
},
error (error) {
console.log('err')
console.error(error)
},
})
When i do mutation after npm run dev and websocket start, i got this error.
But i already made testSub.
php artisan lighthouse:subscription testSub
This is my testSub file.
<?php
namespace App\GraphQL\Subscriptions;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Subscriptions\Subscriber;
use Nuwave\Lighthouse\Schema\Types\GraphQLSubscription;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
use App\Test as Test2;
use App\Events\test;
class TestSub extends GraphQLSubscription
{
/**
* Check if subscriber is allowed to listen to the subscription.
*
* #param \Nuwave\Lighthouse\Subscriptions\Subscriber $subscriber
* #param \Illuminate\Http\Request $request
* #return bool
*/
public function authorize(Subscriber $subscriber, Request $request): bool
{
// TODO implement authorize
return true;
}
/**
* Filter which subscribers should receive the subscription.
*
* #param \Nuwave\Lighthouse\Subscriptions\Subscriber $subscriber
* #param mixed $root
* #return bool
*/
public function filter(Subscriber $subscriber, $root): bool
{
return true;
// TODO implement filter
}
public function encodeTopic(Subscriber $subscriber, string $fieldName): string
{
// Optionally create a unique topic name based on the
// `author` argument.
//$args = $subscriber->args;
//return Str::snake($fieldName).':'.$args['author'];
//return Str::snake($fieldName).':1';
return 'testSub';
}
/**
* Decode topic name.
*
* #param string $fieldName
* #param \App\Post $root
* #return string
*/
public function decodeTopic(string $fieldName, $root): string
{
// Decode the topic name if the `encodeTopic` has been overwritten.
$author_id = $root->author_id;
//return Str::snake($fieldName).':'.$author_id;
return 'testSub';
}
public function resolve($root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Test2
{
event(new test());
return $root;
}
}
How can i get all array data instead of changed data?
In your vue-apollo code you have this:
gql`subscription testSub($id: ID) {
testSub(id:$id) {
id
name
}
}`
So, think that it is like a query. Everytime the subscription is fired, you are querying the id and name. If you want to also query the result, just add it:
gql`subscription testSub($id: ID) {
testSub(id:$id) {
id
name
result # <--
}
}`
There is no way to tell to apollo that has to fetch "all" fields of the Test type. You have to explicit those fields.

My angular frontend App can not send PUT request to my backend REST app

I have two web apps running on a single tomcat instance. One of them is Spring MVC Rest app which has basic structure, a rest controller, a service layer and DAO layer which is interacting with postgresql .
Below you can see my RestController
package com.hizir.acil.main.controller;
import com.hizir.acil.main.model.Donor;
import com.hizir.acil.main.service.DonorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;
import org.joda.time.*;
import javax.validation.Valid;
import java.util.List;
/**
* Created by TTTDEMIRCI on 12/29/2015.
*/
#RestController
#RequestMapping("/")
public class AppController {
#Autowired
DonorService donorService;
#Autowired
MessageSource messageSource;
/*
* This method will list all existing Donors in for JSP .
*/
#RequestMapping(value = { "/", "/listAllDonors" }, method = RequestMethod.GET)
public String listDonors(ModelMap model) {
List<Donor> donors = donorService.findAllDonors();
model.addAttribute("donors", donors);
return "alldonors";
}
/*
* This method will list all existing Donors in json format.
*/
#RequestMapping(value = { "/listjson" }, method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<List<Donor>> listDonors() {
List<Donor> donors = donorService.findAllDonors();
if (donors.isEmpty()) {
return new ResponseEntity<List<Donor>>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<List<Donor>>(donors, HttpStatus.OK);
}
/*
* This method will provide the medium to add a new donor.
*/
#RequestMapping(value = { "/new" }, method = RequestMethod.GET)
public String newDonor(ModelMap model) {
Donor donor = new Donor();
model.addAttribute("donor", donor);
model.addAttribute("edit", false);
return "registration";
}
//-------------------Create a Donor--------------------------------------------------------
#RequestMapping(value = "/listjson", method = RequestMethod.POST)
public ResponseEntity<Void> createUser(#RequestBody Donor donor, UriComponentsBuilder ucBuilder) {
System.out.println("Creating Donor " + donor.getName());
// if (donorService.isUserExist(user)) {
// System.out.println("A User with name " + user.getUsername() + " already exist");
// return new ResponseEntity<Void>(HttpStatus.CONFLICT);
// }
donor.setCreationDate(new LocalDate());
donorService.saveDonor(donor);
System.out.println("donor created.............."+donor.getId());
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/listjson/{id}").buildAndExpand(donor.getId()).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
//------------------- Update a donor --------------------------------------------------------
#RequestMapping( method = RequestMethod.PUT)
public ResponseEntity<Donor> updateUser(#PathVariable("id") int id, #RequestBody Donor donor) {
System.out.println("Updating donor " + id);
Donor currentDonor = donorService.findById(id);
// if (currentUser==null) {
// System.out.println("User with id " + id + " not found");
// return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
// }
currentDonor.setName(donor.getName());
currentDonor.setSurname(donor.getSurname());
currentDonor.setBloodType(donor.getBloodType());
donorService.updateDonor(currentDonor);
return new ResponseEntity<Donor>(currentDonor, HttpStatus.OK);
}
/*
* This method will be called on form submission, handling POST request for
* saving donor in database. It also validates the user input
*/
#RequestMapping(value = { "/new" }, method = RequestMethod.POST)
public String saveDonor(#Valid Donor donor, BindingResult result,
ModelMap model) {
if (result.hasErrors()) {
return "registration";
}
donorService.saveDonor(donor);
model.addAttribute("success", "Donor " + donor.getName() + " registered successfully");
return "success";
}
/*
* This method will provide the medium to update an existing Donor.
*/
#RequestMapping(value = { "/edit-{id}-donor" }, method = RequestMethod.GET)
public String editDonor(#PathVariable int id, ModelMap model) {
Donor donor= donorService.findById(id);
model.addAttribute("donor", donor);
model.addAttribute("edit", true);
return "registration";
}
/*
* This method will be called on form submission, handling POST request for
* updating donor in database. It also validates the user input
*/
#RequestMapping(value = { "/edit-{id}-donor" }, method = RequestMethod.POST)
public String updateDonor(#Valid Donor donor, BindingResult result,
ModelMap model, #PathVariable int id) {
if (result.hasErrors()) {
return "registration";
}
// if(!service.isEmployeeSsnUnique(employee.getId(), employee.getSsn())){
// FieldError ssnError =new FieldError("employee","ssn",messageSource.getMessage("non.unique.ssn", new String[]{employee.getSsn()}, Locale.getDefault()));
// result.addError(ssnError);
// return "registration";
// }
donorService.updateDonor(donor);
model.addAttribute("success", "Donor " + donor.getName() + " updated successfully");
return "success";
}
/*
* This method will delete a donor by it's id value.
*/
#RequestMapping(value = { "/delete-{id}-donor" }, method = RequestMethod.GET)
public String deleteDonorById(#PathVariable int id) {
donorService.deleteDonorById(id);
return "redirect:/listAllDonors";
}
}
As you can see there are several request mappings. Listing donors and creating donor is working fine with frontend app and I can create new donor and list them. But when I try to update any request is not accessing this rest controller method.
Below is my angular service of frontedn app.
App.factory('User', [
'$resource',
function($resource) {
return $resource(
'http://localhost:8080/HizirAcilBackendApp/listjson/:id', {id: '#id'}, {
update : {
method : 'PUT'
}
},
{
stripTrailingSlashes: false
});
} ]);
and below is my angular controller
/**
*
*/
'use strict';
App.controller('UserController', ['$scope', 'User', function($scope, User) {
var self = this;
self.user= new User();
self.users=[];
self.fetchAllUsers = function(){
self.users = User.query();
};
self.createUser = function(){
self.user.$save(function(){
self.fetchAllUsers();
});
};
self.updateUser = function(){
self.user.$update(function(){
self.fetchAllUsers();
});
};
self.deleteUser = function(identity){
var user = User.get({id:identity}, function() {
user.$delete(function(){
console.log('Deleting user with id ', identity);
self.fetchAllUsers();
});
});
};
self.fetchAllUsers();
self.submit = function() {
if(self.user.id==null){
console.log('Saving New User', self.user);
self.createUser();
}else{
console.log('Upddating user with id ', self.user.id);
self.updateUser();
console.log('User updated with id ', self.user.id);
}
self.reset();
};
self.edit = function(id){
console.log('id to be edited', id);
for(var i = 0; i < self.users.length; i++){
if(self.users[i].id === id) {
self.user = angular.copy(self.users[i]);
break;
}
}
};
self.remove = function(id){
console.log('id to be deleted', id);
if(self.user.id === id) {//If it is the one shown on screen, reset screen
self.reset();
}
self.deleteUser(id);
};
self.reset = function(){
self.user= new User();
$scope.myForm.$setPristine(); //reset Form
};
}]);
I am trying to learn Angular,rest and spring all in one place and I think I have made a good progress but I stuck with this PUT request problem.
Any help and comment would be appreciated.
Regards
Turkmen
Looks like your RequestMapping is wrong, you did not specify a path there :
#RequestMapping( method = RequestMethod.PUT)
You need to set a apth and add {id} so spring can map it as #PathVariable
#RequestMapping(value = "/listjson/{id}", method = RequestMethod.POST)

How do I create a custom object class that's available to my methods in AngularJS

I'm a huge fan of angular but it's got some tricky concepts with extremely nuanced differences between them and this is one of them.
I just want to create an class that I can use to create custom objects in my Angular controllers and factories. It surely shouldn't be that hard but I can't figure out how to do it. I want to have a custom, ResultSet class which I can instantiate to create instances of ResultSet. However for the life of me I can't figure out the correct syntax of factory v. service to use.
This is all I want:
ResultSet = function(dataSet){
this.filter = function(){
# filters and returns dataSet
# ...
}
}
and then I want to be able instantiate an instance of ResultSet inside a controller etc:
MyApp.controller('pageCtrl', ['ResultSet', (ResultSet) ->
# ...
rs = ResultSet.new(dataToFilter)
How can I create a service that allows me to create instances of my custom object?
It seems more correct to use an Angular Service rather than a Factory since a service returns an instance of an object (which is exactly what I want). But I can't figure out how to do this...
How would I use a service to declare my custom ResultSet class and then how would I instantiate an instance from it?
Maybe you were looking for something like this:
.factory('User', function (Organisation) {
/**
* Constructor, with class name
*/
function User(firstName, lastName, role, organisation) {
// Public properties, assigned to the instance ('this')
this.firstName = firstName;
this.lastName = lastName;
this.role = role;
this.organisation = organisation;
}
/**
* Public method, assigned to prototype
*/
User.prototype.getFullName = function () {
return this.firstName + ' ' + this.lastName;
};
/**
* Private property
*/
var possibleRoles = ['admin', 'editor', 'guest'];
/**
* Private function
*/
function checkRole(role) {
return possibleRoles.indexOf(role) !== -1;
}
/**
* Static property
* Using copy to prevent modifications to private property
*/
User.possibleRoles = angular.copy(possibleRoles);
/**
* Static method, assigned to class
* Instance ('this') is not available in static context
*/
User.build = function (data) {
if (!checkRole(data.role)) {
return;
}
return new User(
data.first_name,
data.last_name,
data.role,
Organisation.build(data.organisation) // another model
);
};
/**
* Return the constructor function
*/
return User;
})
From this post by Gert Hengeveld.
myApp.factory('ResulSet', function() {
function ResultSetInstance(dataSet) {
this.filter = function(){
// ...
}
}
return {
createNew: function(dataSet) {
return new ResultSetInstance(dataSet);
}
};
});
and then
myApp.controller('pageCtrl', function(ResultSet) {
var someData = ...;
var rs = ResultSet.createNew(someData);
}
Edit (from the question asker)
On experimenting with this further I found that you didn't even need to have the createNew method.
myApp.factory('ResultSetClass', function() {
ResultSetClass = function(dataSet) {
this.filter = function(){
// ...
}
}
return ResultSetClass
});
works just fine and then you can call new ResultSetClass(args).
Note for those using Coffeescript
Coffeescript will return the last variable or method in your class instance so if you are using coffeescript (as a general rule), it's imperative to return this at the end of the class definition
myApp.factory 'ResultSetClass', () ->
ResultSetClass = (dataset) ->
this.filter = () ->
# do some stuff
return this
return ResultSetClass
If you don't return this explicitly then you'll find that when you call
myApp.factory 'ResultSetClass', () ->
ResultSetClass = (dataset) ->
this.filter = () ->
# do some stuff
then you'll simply be left with the last thing the coffeescript returns which is the filter method.
I recently has do do something like that because I wanted to implement a factory of class instance, and being able to configurate my instances and benefit from Angular Dependency injection. I ended up with something like that
// Implem
export class XAPIService {
private path: string;
/* this DO NOT use angular injection, this is done in the factory below */
constructor(
private seed: XAPISeed,
private $http: ng.IHttpService,
private slugService: SlugService
) {
const PATH_MAP: Map<Y, Z> = new Map([
['x', id => `/x/${id}`],
['y', id => `/y/${id}`],
]);
this.path = PATH_MAP.get(this.seed.type)(this.seed.id);
}
list() {
/* implem that use configured path */
return this.slugService
.from(this.path + `/x`)
.then(url => this.$http.get<IX>(url))
.then(response => response.data)
}
}
export type IXAPIFactory = (s: XAPISeed) => XAPIService;
export function XAPIFactory(
$http: ng.IHttpService,
myService: SlugService
) {
'ngInject';
return (seed: XAPISeed) =>
new XAPIService(seed, $http, myService);
}
// angular
angular.module('xxx', [])
.factory('xAPIFactory', XAPIFactory)
// usage in code
export class XsController implements ng.IComponentController {
/* #ngInject */
constructor(
private xAPIFactory: IXAPIFactory,
) {}
$onInit() {
this.xService = this.xAPIFactory({ id: 'aaabbbaaabbb', type: 'y' });
return this.xService.list()
.then(xs => {
this.xs = xs;
})
}
}

Generic type name injection

I'm writing my angular app in typescript.
For sake of redundancy prevention I would like to accomplish some type of generic handling.
This is where I'm coming from:
class BaseProvider {
api_url = 'http://localhost:80/api/FILL_OUT_PATH/:id';
$get($resource){
var provider = $resource(this.api_url, {}, {
update: {
method: 'PUT'
}
});
return provider;
}
}
and
class User extends BaseProvider{
constructor() {
super();
this.api_url = 'http://localhost:80/api/users/:id';
}
}
then
module Controllers
{
export class BaseController {
message = "Base controller";
entity : any;
entities : any;
constructor($scope)
{
}
}
}
and
module Controllers
{
export class UserController extends BaseController {
name = "UserController";
constructor($scope, User)
{
super($scope);
this.entity = new User();
this.entities = User.query();
$scope.vm = this;
}
}
}
This is where I'd like to go with UserController (P-Code):
module Controllers
{
export class UserController<T extends BaseProvider> extends BaseController {
name = "UserController";
static $inject = ['$scope', T.typename]; // Inject the types name somehow?
constructor($scope, entity)
{
super($scope);
this.entity = new T();
this.entities = T.query();
$scope.user = this;
}
}
Is there a facility in typescript to handle this?
Is there a facility in typescript to handle this?
No. All type information is erased from the generated JS so you cannot use generic parameters as variables.
There is no way to do it with generics since there will be no typing related information at the runtime, but as a workaround you can pass the type via constructor and type safety with generics. The following code compiles without error and shows how it could be accomplished.
class C1 {
m() { }
}
class C2 extends C1 { }
class C<T extends C1> {
constructor(t: { new (): C1 }) {
var instance = new t();
}
}
new C(C2);

Resources