I'm trying to add a popup that's supposed to be displayed when the user naviagates to a new page if certain conditions are met. The problem is that even if I add a post render step to the router configuration, on views that are composed by several custom elements they sometimes import resources after the post render step has executed which causes the popup to dissapear and pretty much lock the page. This is a small reproducable example:
router.configure(config => {
config.addPostRenderStep(CustomPostRenderStep);
return config;
});
...
#inject(DialogService)
class CustomPostRenderStep{
constructor(
private mDialogService: DialogService
) {
}
run(navigationInstruction: NavigationInstruction, next: Next) {
this.mDialogService.open({
viewModel: TestModal
lock: true
});
return next();
}
}
The popup will on some pages appear on the screen for a brief moment before it disappears but the body html tag will still have the class "ux-dialog-open".
Adding a timeout helps, but how long the timeout needs to be is different on different systems which makes it an unreliable solution. Like this:
#inject(DialogService)
class CustomPostRenderStep{
constructor(
private mDialogService: DialogService
) {
}
run(navigationInstruction: NavigationInstruction, next: Next) {
window.setTimeout(() => {
this.mDialogService.open({
viewModel: TestModal
lock: true
});
}, 200);
return next();
}
}
What is the proper way to wait for everything to be rendered before displaying the popup?
A better option would be to utilize events fired by router after navigation success
https://ilikekillnerds.com/2015/09/understanding-aurelia-router-events/
you can subscribe to router:navigation:success in your app and create your dialog aferwards
router:navigation:success
You should use TaskQueue in order to be called on the next rendering loop.
See: http://aurelia.io/docs/api/task-queue/class/TaskQueue/method/queueTask
This should work:
#inject(DialogService, TaskQueue)
class CustomPostRenderStep {
constructor(
private mDialogService: DialogService
private mTaskQueue: TaskQueue
) {
}
run(navigationInstruction: NavigationInstruction, next: Next) {
this.mTaskQueue.queueTask(() => {
this.mDialogService.open({
viewModel: TestModal,
lock: true
});
});
return next();
}
}
I do not really know the RenderPipeline very well but maybe you could call next() inside your queued task.
View my Gist fork that is working, maybe you should investigate what is closing your dialog by setting breakpoints in aurelia-dialog code.
Here's an example: Aurelia Router Demo | PostRenderStep modal dialog example
app.js
import { inject } from 'aurelia-framework';
import { DialogService } from 'aurelia-dialog';
import { TestModal} from 'test-modal';
export class App {
configureRouter(config, router) {
config.title = 'Aurelia';
config.map([
{route: ['', 'home'], name: 'home', moduleId: 'home/home', nav: true, title: 'Home'},
{route: 'profile', name: 'profile', moduleId: 'profile/profile', nav: true, title: 'Profile'},
{route: 'settings', name: 'settings', moduleId: 'settings/settings', nav: true, title: 'Settings'}
]);
config.addPostRenderStep(PostRenderStep);
this.router = router;
}
}
#inject(DialogService, TestModal)
class PostRenderStep {
constructor(dialogService, testModal){
this.dialogService = dialogService;
this.testModal = testModal;
}
run(routingContext, next) {
this.dialogService.open({
viewModel: TestModal,
lock: true
});
return next();
}
}
Plus, which versions are you using?
Related
So i'm using Postman and i need to send a POST method request to my api but every time i do it hangs even if the handler does nothing except return a simple value. I'm using hapi so the syntax might differ a little bit from the standard express app.
currency.ts
//this is where i define the route methods and paths
import * as Hapi from "hapi";
import IRouteArea from "../server/IRouteArea";
import CurrencyController from "../controller/CurrencyController";
import hapiAuthJwt2 = require("hapi-auth-jwt2");
import { join } from "lodash";
import { RESOLVER } from "awilix";
const CurrencyArea = ({ currencyController }: any): IRouteArea => {
let _controller = currencyController as CurrencyController;
return {
registerRoutes(server: Hapi.Server) {
server.bind(_controller);
server.route({
method: "GET",
path: "/api/currencies",
options: {
auth: {
mode: "try"
},
plugins: { "hapi-auth-cookie": { redirectTo: false } },
handler: _controller.getCurrencies
}
});
server.route({
method: "POST", // this one is causing me problems
path: "/api/currencies/{id}",
options: {
auth: {
mode: "try"
},
plugins: { "hapi-auth-cookie": { redirectTo: false }},
handler: _controller.editCurrency
}
});
}
};
};
export default CurrencyArea;
and even though the actual handler of the request isn't doing anything special...
CurrencyController.ts
//here i define the handlers of requests sent to routes in the previous file
import * as Hapi from "hapi";
import { name } from "mustache";
import GetCurrencyListInteractor from "../../interactor/currencies/GetCurrencyListInteractor";
import Task from "../../runtime/Task";
export default class CurrencyController {
private task: Task;
constructor({ task }: any) {
this.task = task;
}
public async getCurrencies(
request: Hapi.Request,
h: Hapi.ResponseToolkit
): Promise<any> {
try {
return this.task.start<GetCurrencyListInteractor>(
"getCurrencyList",
t => t.execute()
);
} catch (error) {
return error as any;
}
}
public async editCurrency( //it's supposed to just return the parameter sent in the url
request: Hapi.Request,
h: Hapi.ResponseToolkit
): Promise<any> {
try {
return request.params.id;
} catch (error) {
return error as any;
}
}
}
it always hangs and gets stuck on the "sending request" screen when i send the request. One interesting thing is that the exact same route works as intended but only if the method defined in currency.ts is "GET". If i leave everything else the way it is and change the method from "GET" to "POST" or "PUT" or "PATCH" it stops working.
this goes on forever
I have Single sign on in place but for testing I want to read the values from the url localhost:4200/?id=test&name=testing&email=testing#test.com and pass them to an API in app component.
there will be a flag on which basis I will reading from url instead of using single sign on function
if (url_enabled == true) {
getParamsFromUrl()
} else {
singleSignOn()
}
I tried ActivatedRoute but it doesn't seem to be working.
I have tried queryParams, params, url, queryParamsMap but none of these seems to be working. all I get is empty value.
inside app component
app.component.ts
getParamsFromUrl() {
this._router.events.subscribe((e) => {
if (e instanceof NavigationEnd) {
console.log(e.url)
}
})
}
this.route.queryParams.subscribe(params => {
console.log(params);
})
app.component.html
<router-outlet></router-outlet>
app-routing.module.ts
const routes: Routes = [
{path:'*/:id', component: AppComponent},
];
I have tried whatever I could found on stackoverflow or other blogs. Can somebody point out what am I missing here?
For this route:
You can try this way:
const routes: Routes = [
{path:'*/:id', component: AppComponent},
];
In AppComponent .ts file:
constructor(
private activatedRoute: ActivatedRoute,
) { }
ngOnInit() {
this.activatedRoute.params.subscribe(params => {
const id = params['id'];
console.log('Url Id: ',id);
}
OR
ngOnInit() {
this.activatedRoute.queryParams.subscribe(params => {
const id = +params.id;
if (id && id > 0) {
console.log(id);
}
});
}
first of all there is an url with queryParams like yours :
localhost:4200/?id=test&name=testing&email=testing#test.com
in this way tou get to the queryparams with ActivatedRoute object lik :
this.name = this.activatedRoute.snapshot.queryParamMap.get('name'); // this.name = 'testing'
Or :
this.activatedRoute.queryParams.subscribe(params => {
this.name= params['name'];
});
and the other way is
localhost:4200/test/testing/testing#test.com
you use for sync retrieval (one time) :
this.name = this.activatedRoute.snapshot.ParamMap.get('name');
Angular comes us with the ActivatedRoute object. We can access the URL parameter value in same way its done above with little difference. Data in this type can be accessed with two different ways. One is through route.snapshot.paramMap and the other is through route.paramMap.subscribe. The main difference between the two is that the subscription will continue to update as the parameter changes for that specific route.
ngOnInit() {
this.route.paramMap.subscribe(params => {
this.userType = params.get("userType")
})
}
You need to create a new component and update the routing configuration as follows:
First, create a new component: MainComponent:
import { Component } from '#angular/core';
#Component({
selector: 'main',
template: `<router-outlet></router-outlet>`,
})
export class MainComponent {
constructor() { }
}
Then, update your AppModule:
import { AppComponent } from './app.component';
import { MainComponent } from './main.component';
#NgModule({
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot([
{path: '', component: AppComponent}
])
],
declarations: [ MainComponent, AppComponent ],
bootstrap: [ MainComponent ]
})
export class AppModule { }
Finally, you'll need to update your index.html file(Make sure to load the brand new component instead of the AppComponent):
<main>loading</main>
Now you'll be able to read your parameters as requested in your AppComponent:
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute, Params } from '#angular/router';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
params: Params;
constructor(private route: ActivatedRoute){}
ngOnInit() {
this.route.queryParams.subscribe((params: Params) => {
this.params = params;
console.log('App params', params);
const id = params['id'];
console.log('id', id);
});
}
}
See a working example here: https://read-params-app-component.stackblitz.io/?id=test&name=testing&email=testing#test.com.
And find the source code here.
I hope it helps!
You can try like this
constructor(
private activatedRoute: ActivatedRoute
)
ngOnInit() {
this.activatedRoute.paramMap
.pipe(
tap(console.log(this.activatedRoute.snapshot.paramMap.get(
"id"
)))
).subscribe()
}
Let me know if you need any help
Using Transition from #uirouter/core makes it easy to get params from url.
import {Transition} from '#uirouter/core';
#Component()
export class MyComponent {
public myParam = this.transition.params().myParam;
public constructor(public transition: Transition) {}
}
I used jquery inside angular 8 and got the href using jquery $ variable after declaring it in app component.
import { query } from '#angular/animations';
declare var $: any;
I am creating test application using angular so in that i need to display user details while i click on edit button then, that user details will need to display in another component.i have written query to get user details while clicking edit button, but unable to get data so what is the exact procedure for changes need to be done in query.
This is my manageusers.component.html
<tr *ngFor="let detail of userDetails" style="text-align:center">
<td><input type="checkbox"></td>
<td>{{detail.username}}</td>
<td>{{detail.uemail}}</td>
<td>Inactive</td>
<td>{{detail.added_on}}</td>
<td>
<a routerLink="/dashboard-info/basic-settings">
<i class="fas fa-edit" (click)="editIssue(i,detail._id)"></i>
</a>
This is my manageusers.component.ts
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup , Validators } from '#angular/forms';
import { DataService } from '../../../services/data.service';
import { AccountService } from '../../../services/account.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-manage-users',
templateUrl: './manage-users.component.html',
styleUrls: ['./manage-users.component.css'],
})
export class ManageUsersComponent implements OnInit {
userDetails:any = [];
detail:Detail={
added_on:'',
username:'',
uemail:'',
upassword:'',
};
constructor(private router: Router,private fb:FormBuilder,private dataService: DataService, private accountService: AccountService) {}
editIssue(id,detail){
alert(detail);
let data = {
_id:detail,
};
this.accountService.editDetail(data).subscribe(
response => {
console.log(response);
this.userDetails = JSON.parse(response);
//this.router.navigate(['/dashboard-info/basic-settings', this.userDetails]);
},
err => {
console.error('User Not found');
})
}
ngOnInit() {}
}
interface Detail{
added_on:string
username:string,
upassword:string,
uemail:string,
}
accountService.ts
editDetail(data) {//Getting User with userId
return this.http.post(this.apiPath + 'user/editDetail', data,{responseType: 'text'});
}
usercontroller.js
userRouter.post('/editDetail', function (req, res) {
console.log(req.body._id);
Collections.user.findOne({_id: req.body._id}, function (err, result) {
if (err) return res.status(500).send("There was a problem finding the user");
if (result) {
console.log(result);
res.status(200).send(result);
} else {
return res.status(500).send("User Not Found with Details: " + JSON.stringify(user));
}
});
});
I think it would be better to set the User you want to show in the component as input, get the User you need in an http call and pass it to the component afterwards by it's input. See more for component input here: https://toddmotto.com/passing-data-angular-2-components-input
To retrieve data by http call you should use Angulars Http Client, which is really easy to use and saves you from using plain javascript. See here: https://blog.angular-university.io/angular-http/
I have this very basic project:
https://github.com/napolev/ionic-start
which is basically the Ionic starter project:
// https://ionicframework.com/getting-started
$ ionic start ionic-start tabs
I added the following two files:
/src/extras/social-media.ts
import * as Promise from 'bluebird';
import { User } from './user';
export var LoginPromise = function(service): Promise<string> {
return new Promise((resolve) => {
setTimeout(function(){
resolve('Will Smith');
}, 2000)
});
};
//*/ IF I COMMENT THIS BLOCK OUT, THERE IS NO ERROR
// this function is not used by this project
// but for some specific reasons it is required to be here
// this code is a simplification of a bigger project
export var callMeIfYouNeedMe = function(id) {
return new Promise((resolve) => {
User.findById(id, function(err, user) {
console.log(user);
resolve(user);
});
});
}
// END OF BLOCK */
/src/extras/user.ts
import { Document, Schema, Model, model} from "mongoose";
export interface IUser {
name: string;
}
export interface IUserDocument extends IUser, Document {
}
export var UserSchema: Schema = new Schema({
name: String,
});
export const User: Model<IUserDocument> = model<IUserDocument>("User", UserSchema);
The code right above works properly on a node project (I tried by myself). I got it from: http://brianflove.com/2016/10/04/typescript-declaring-mongoose-schema-model/#schema--model
With the last export I create a model of type: IUserDocument.
I also modified the following two files:
/src/pages/home/home.ts
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { LoginPromise } from '../../extras/social-media';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController) {
}
test() {
console.log('Hello World');
LoginPromise('facebook').then(
(name: string) => {
console.log('### Social Media -> ' + name);
}
);
}
}
/src/pages/home/home.html
<ion-header>
<ion-navbar>
<ion-title>Home</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h2>Welcome to Ionic!</h2>
<p>
This starter project comes with simple tabs-based layout for apps
that are going to primarily use a Tabbed UI.
</p>
<p>
Take a look at the <code>src/pages/</code> directory to add or change tabs,
update any existing page or create new pages.
</p>
<button ion-button (click)="test()" color="primary">Test</button>
</ion-content>
My problem, is that when I run:
$ ionic serve --no-open
I don't get any error on the console, but on the browser I get the following:
"Runtime Error: Object(...) is not a function"
as you can see here:
Do you have any idea about what could be going on here and how can I make this work?
Thanks!
Runtime Error: Object(…) is not a function
Your call :
model<IUserDocument>("User", UserSchema);
is wrong. model is not a function. Its an object.
Fix
Don't invoke an object. The code is wrong.
Good afternoon! I'm new in Angular 2, so I'm sorry in advance if my question is generic. I cannot figure out how to handle an API response.
My NodeJS Server API function is (Checked and works fine):
router.get('/appointment/:iatreio/:time', function(req, res, next) {
var paramIatreio = req.params.iatreio;
var paramTime = req.params.time;
db.appointments.findOne({iatreio: paramIatreio, time: req.params.time}, function(err, resultFound) {
if (err) { res.send(err); }
if (resultFound) {
res.json(true); // 1st Question: For best practice, res.json(true) or res.send(true)?
} else {
res.json(false);
}
});
});
My Angular2 Service:
import { Injectable } from '#angular/core';
import { Headers , Http } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
#Injectable()
export class AppointmentService {
constructor(private http: Http) { }
isBooked(iatreio: string, time: string): Observable<boolean> {
return this.http
.get('http://localhost:3000/appointment/'+iatreio+'/'+time)
.map(); //2nd Question: What inside map()?
}
} // end of Service
Component Function
isBooked(selectedIatreio: string, selectedTime: string): boolean {
this.appointmentService
.isBooked(selectedIatreio, selectedTime)
.subscribe(() => {}); //3rd Question: What inside subscribe()?
}
My final goal is the "isBooked(...)" function of my Component to be called and to return true or false. I have seen the code in the examples in the Angular2 site, but I'm a little confused on my case.
Can Service function return directly a true or false value or it has to be an Observable?? Map() function is necessary??
Generally, my thinking is right?? Or my goal can be accomplished more easily??
Thank you a lot for your time!!
map is used to convert the response into the model which you look for
isBooked(iatreio: string, time: string): Observable<boolean> {
return this.http
.get('http://localhost:3000/appointment/'+iatreio+'/'+time)
.map((response)=><boolean>response.json());
}
subscribe will return the data emitted by the service
isBooked(selectedIatreio: string, selectedTime: string): boolean {
this.appointmentService
.isBooked(selectedIatreio, selectedTime)
.subscribe((data) => {
//your operation
console.log(data);
});
}