I am working with Angular2 and es5. I want to use http in a service.
Unfortunately I have 2 errors:
- http is undefined, but ng.http.Http is defined,
- I have this error for the main component:
vendor-client.min.js:28 EXCEPTION: Can't resolve all parameters for class0: (t, ?)
Here is my service code:
;(function(app, ng) {
console.log(new ng.http.Http());
app.ApplicationsService = ng.core.Injectable().Class({
constructor: [ng.http.Http, function(http) {
console.log(http);
this.applicationsEmailUrl = 'api/applications/email';
this.http = http;
}],
emailExists: function(email) {
console.log(email);
var data = { email: email };
return this.http.post(this.applicationsEmailUrl, data)
.toPromise()
.then(function(response) { response.json().data; })
.catch(this.handleError);
}
});
})(window.app || (window.app = {}), window.ng);
Here is the main component:
;(function(app, ng) {
app.AppComponent = ng.core
.Component({
selector: 'register-form',
templateUrl: 'src/register/app.component.html'
})
.Class({
constructor: [ng.core.ElementRef, app.ApplicationsService, function(ref, Applications) {
console.log('app.component.js');
this.programs = JSON.parse(ref.nativeElement.getAttribute('programs'));
this.applications = Applications;
}],
emailExists: function(email) {
console.log('emailExists() triggered');
Applications.emailExists(email);
}
});
})(window.app || (window.app = {}), window.ng);
The bootstrap:
;(function(app, ng) {
document.addEventListener('DOMContentLoaded', function() {
ng.platformBrowserDynamic.bootstrap(app.AppComponent, [
ng.forms.disableDeprecatedForms(),
ng.forms.provideForms(),
ng.http.HTTP_PROVIDERS,
app.ApplicationsService
]);
});
})(window.app || (window.app = {}), window.ng);
If I try to inject http into the main component within the providers array, it works. But I would rather prefer to have a service.
I found out the problem. Looks like Angular2 needs to load your code in order. The main component was loaded before the service, so it was undefined. I put all my code in one file and it works. I will use a require loader asap.
Related
I want to add a console panel to my html page like in the REPL page of the svelte site.
https://svelte.dev/repl/hello-world?version=3.55.1
My site was generating as a static site and copy in an ESP8266 micro controller.
I have no idea how to do that :-(
The REPL overwrites the methods of the console object to extend them.
E.g. for the methods that write messages:
['clear', 'log', 'info', 'dir', 'warn', 'error', 'table'].forEach((level) => {
const original = console[level];
console[level] = (...args) => {
const stringifiedArgs = stringify(args);
if (previous.level === level && previous.args && previous.args === stringifiedArgs) {
parent.postMessage({ action: 'console', level, duplicate: true }, '*');
} else {
previous = { level, args: stringifiedArgs };
try {
parent.postMessage({ action: 'console', level, args }, '*');
} catch (err) {
parent.postMessage({ action: 'console', level: 'unclonable' }, '*');
}
}
original(...args);
};
});
Source
This uses postMessage to send a message event containing the logged contents, but you could use other mechanisms as well.
I'm using strapi 4 with nextjs.
In the app strapi holds music events for each user and each user should be able add and retrieve there own music events.
I am having trouble retrieving
each users music events from strapi 4
I have a custom route and custom controller
The custom route is in a file called custom-event.js and works ok it is as follows:
module.exports = {
routes: [
{
method: 'GET',
path: '/events/me',
handler: 'custom-controller.me',
config: {
me: {
auth: true,
policies: [],
middlewares: [],
}
}
},
],
}
The controller id a file called custom-controller.js and is as follows:
module.exports = createCoreController(modelUid, ({strapi }) => ({
async me(ctx) {
try {
const user = ctx.state.user;
if (!user) {
return ctx.badRequest(null, [
{messages: [{ id: 'No authorization header was found'}]}
])
}
// The line below works ok
console.log('user', user);
// The problem seems to be the line below
const data = await strapi.services.events.find({ user: user.id})
// This line does not show at all
console.log('data', data);
if (!data) {
return ctx.notFound()
}
return sanitizeEntity(data, { model: strapi.models.events })
} catch(err) {
ctx.body = err
}
}
}))
Note there are two console.logs the first console.log works it outputs the user info
The second console.log outputs the data it does not show at all. The result I get back
using insomnia is a 200 status and an empty object {}
The following line in the custom-controller.js seems to be where the problem lies it works for strapi 3 but does not seem to work for strapi 4
const data = await strapi.services.events.find({ user: user.id})
After struggling for long time, days infact, I eventually got it working. Below is the code I came up with. I found I needed two queries to the database, because I could not get the events to populate the images with one query. So I got the event ids and then used the event ids in a events query to get the events and images.
Heres the code below:
const utils = require('#strapi/utils')
const { sanitize } = utils
const { createCoreController } = require("#strapi/strapi").factories;
const modelUid = "api::event.event"
module.exports = createCoreController(modelUid, ({strapi }) => ({
async me(ctx) {
try {
const user = ctx.state.user;
if (!user) {
return ctx.badRequest(null, [
{messages: [{ id: 'No authorization header was found'}]}
])
}
// Get event ids
const events = await strapi
.db
.query('plugin::users-permissions.user')
.findMany({
where: {
id: user.id
},
populate: {
events: { select: 'id'}
}
})
if (!events) {
return ctx.notFound()
}
// Get the events into a format for the query
const newEvents = events[0].events.map(evt => ({ id: { $eq: evt.id}}))
// use the newly formatted newEvents in a query to get the users
// events and images
const eventsAndMedia = await strapi.db.query(modelUid).findMany({
where: {
$or: newEvents
},
populate: {image: true}
})
return sanitize.contentAPI.output(eventsAndMedia,
strapi.getModel(modelUid))
} catch(err) {
return ctx.internalServerError(err.message)
}
}
}))
So I'm using the native HTTP cordova plugin for my http requests. But I can't seem to wrap my head around a problem where I can't create an alert inside the onFail function. Anyone else experienced this?
The error says:
Error in Error callbackId: CordovaHttpPlugin1608257770 : TypeError: Cannot
read property 'alertCtrl' of undefined
Here's how I structured my code:
cordova.plugin.http.sendRequest('http://127.0.0.1:5000/api/login/', options, function(response) {
try { //onSuccess
response.data = JSON.parse(response.data);
localStorage.setItem('token', JSON.stringify(response.data.token));
} catch(e) {
console.error('JSON parsing error');
}
}, function(response) { //onFail
console.log('403');
let alert = this.alerts.create({
title: 'Error',
subTitle: 'Username/password is invalid!',
buttons: ['Dismiss']
});
alert.present();
}
);
Here's how my constructor looks like:
constructor(public navCtrl: NavController,
private alerts: AlertController,
private http: HTTP,
private store: Storage,
) {}
What's causing it to not work?
Try this, because when you create alert in request "this" means httprequest so that hasn't alert class
let alert = this.alerts.create({
title: 'Error',
subTitle: 'Username/password is invalid!',
buttons: ['Dismiss']
});
cordova.plugin.http.sendRequest('http://127.0.0.1:5000/api/login/', options, function(response) {
try { //onSuccess
response.data = JSON.parse(response.data);
localStorage.setItem('token', JSON.stringify(response.data.token));
} catch(e) {
console.error('JSON parsing error');
}
}, function(response) { //onFail
console.log('403');
alert.present();
}
);
I am trying to use http with Angular2.
Here is my code:
var _domain = 'http://localhost:3000/';
app.Applications = ng.core.Injectable().Class({
constructor: [ng.http.Http, function(http) {
this.http = http;
this.emailExistUrl = _domain + 'api/applications/email';
}],
doesEmailExist: function(email) {
var data = { email: email };
return this.http.post(this.emailExistUrl, data)
.toPromise()
.then(function(response) { response.json().data; })
.catch(this.handleError);
}
});
The main component:
app.AppComponent = ng.core
.Component({
selector: 'register-form',
templateUrl: 'src/register/app.component.html',
providers: [app.Applications]
})
.Class({
constructor: [ng.core.ElementRef, app.Applications, function(ref, Applications) {
this.programs = JSON.parse(ref.nativeElement.getAttribute('programs'));
this.applications = Applications;
}],
doesEmailExist: function(email) {
return this.applications.doesEmailExist(email);
}
});
Here is main.js file:
document.addEventListener('DOMContentLoaded', function() {
ng.platformBrowserDynamic.bootstrap(app.AppComponent, [
ng.forms.disableDeprecatedForms(),
ng.forms.provideForms(),
ng.http.HTTP_PROVIDERS,
]);
});
When doesEmailExist is called I get an error from the http module:
vendor-client.min.js:55470 TypeError: Cannot read property 'platform_browser_private' of undefined
Any ideas?
FIXED:
Http was before platform-browser on the script tag list. :/
<script src="https://npmcdn.com/#angular/http/bundles/http.umd.js"></script>
<script src="https://npmcdn.com/#angular/platform-browser/bundles/platform-browser.umd.js"></script>
<script src="https://npmcdn.com/#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js"></script>
The inverse is better :)
Try to assign http at the beginning of the constructor:
app.Applications = ng.core.Injectable().Class({
constructor: [ng.http.Http, function(http) {
this.http = http;
...
}],
doesEmailExist: function(email) {
...
}
});
EDIT
See this Plunker: http://plnkr.co/edit/aQWqxauklT7MqSjfhLFD. To simplify, I have put everything in main.js file, and instead of an http post I have implemented an http get. However, locally, even the http post works with a web service API. I hope it's helpful to solve your problem.
When trying to read an attribute, meteor gives me a TypeError: Cannot read property 'featuredImage' of undefined error in the browser console. But it reads featuredImage and the site is working fine. How can I get rid of this error? Is it happening because my subscriptions are not yet ready? Is that's the case, how to fix it? (PS : Im using the flow router so I can't wait for subscriptions in the router)
My template code :
Template.About.helpers({
page: () => {
return findPage();
},
featuredImage: () => {
var thisPage = findPage();
return Images.findOne({
"_id": thisPage.featuredImage
});
}
});
function findPage() {
return Pages.findOne({
slug: 'about'
});
}
The router code :
FlowRouter.route('/about', {
name: 'about',
subscriptions: function() {
this.register('page', Meteor.subscribe('pages', 'about'));
this.register('image', Meteor.subscribe('images'));
},
action() {
BlazeLayout.render('MainLayout', {
content: 'About'
});
setTitle('About Us');
},
fastRender: true
});
The subscription is probably not ready yet. FlowRouter provides a utility for dealing with this, your helpers should look like this:
Template.About.helpers({
page: () => {
// If you only need a specific subscription to be ready
return FlowRouter.subsReady('page') && findPage() || null;
},
featuredImage: () => {
// Ensure ALL subscriptions are ready
if ( FlowRouter.subsReady() ) {
var thisPage = findPage();
return Images.findOne({
"_id": thisPage.featuredImage // Probably should be thisPage.featuredImage._id
});
}
return null;
}
});
However, for maximum performance, you should use if (FlowRouter.subsReady('page') && Flowrouter.subsReady('image')) rather than FlowRouter.subsReady() since if you have other pending subscriptions which are large, it will wait for those even though you don't need them.