I am trying to implement the pagination in my angular2 app with the ng2-bootrap. am following http://valor-software.github.io/ng2-bootstrap/#pagination
my app.html
<div>
<div class="col-lg-12 text-right">
<pagination [totalItems]="bigTotalItems" (page-changed)="pageChanged($event)" [(ngModel)]="bigCurrentPage" [maxSize]="maxSize"
class="pagination-sm" [boundaryLinks]="true"></pagination>
</div>
</div>
my component
import { Component, View, Inject} from 'angular2/core';
import { CORE_DIRECTIVES } from 'angular2/common';
import { PAGINATION_COMPONENTS } from 'ng2-bootstrap/ng2-bootstrap';
// webpack html imports
#View({
templateUrl: '/scripts/src/components/demo/demo.html',
directives: [PAGINATION_COMPONENTS, CORE_DIRECTIVES]
})
#Component({
selector: 'tabs-demo',
})
export class DemoComponent {
private totalItems: number = 64;
private currentPage: number = 4;
private maxSize: number = 5;
private bigTotalItems: number = 175;
private bigCurrentPage: number = 1;
private setPage(pageNo: number): void {
this.currentPage = pageNo;
};
private pageChanged(event: any): void {
console.log('Page changed to: ' + event.page);
console.log('Number items per page: ' + event.itemsPerPage);
};
}
but when i change the pagination page its not triggering the pagechanged event.
Please correct me to work it properly.
The Output is called pageChanged, not page-changed
Related
I am not able to figure out how to inform a new registering user that email is already registered below the input element on entering email on my front-end in angular. Please assist. I am able to retrieve my async validation response as to whether the email is already registered or is available. I am using PrimeNG components and scss
In my Network Response, API response, I see {"email":"This eamil is already registered"} if the email is already registered and if the email is not registered, {"available":true}.
Below is the code for async validator in my unique-email.ts.
export class UniqueEmail implements AsyncValidator {
constructor(private authService: AuthService) {}
validate = (control: AbstractControl) => {
const { value } = control;
return this.authService.emailAvailable(value).pipe(
map((value) => {
if (value.available) {
return null;
}
}),
catchError((err) => {
if (err.error.email) {
return of({ EmailInUse: true });
} else {
return of({ noConnection: true });
}
})
);
};
}
Below is my code for AuthService.ts
interface EmailAvailableResponse {
available: boolean;
}
export class AuthService {
apiURLAuth = environment.apiUrl + 'users';
constructor(private http: HttpClient) {}
emailAvailable(email: string) {
return this.http.post<EmailAvailableResponse>(`${this.apiURLAuth}/emailexist`, {
email
});
}
}
My signup.component.ts
export class SignupComponent implements OnInit {
signupFormGroup: FormGroup;
isSubmitted = false;
authError = false;
constructor(
private matchPassword: MatchPassword,
private uniqueEmail: UniqueEmail,
private formBuilder: FormBuilder,
private authService: AuthService,
private localstorageService: LocalstorageService
) {}
private _initSignupForm() {
this.signupFormGroup = this.formBuilder.group(
{
email: ['', [Validators.required, Validators.email], [this.uniqueEmail.validate]]
}
)
}
get isignupForm() {
return this.signupFormGroup.controls;
}
}
<form [formGroup]="signupFormGroup">
<div class="col-12">
<div class="p-inputgroup">
<span class="p-inputgroup-addon"><i class="pi pi-id-card"></i></span>
<input type="text" formControlName="email" pInputText placeholder="Email" />
</div>
<small *ngIf="isignupForm.email.invalid && isSubmitted" class="p-error"
><span *ngIf="isignupForm.email.errors.required">Email is required</span>
<span *ngIf="isignupForm.email.errors.email">Email is Invalid</span>
<span *ngIf="isignupForm.email.errors.email.EmailInUse"
>Email is already registered to another user. Try another email account</span
>
</small>
</div>
</form>
There is an error for
isignupForm.email.errors.email.EmailInUse
Instead, use:
<span *ngIf="isignupForm.email.errors.EmailInUse">
Email is already registered to another user. Try another email account
</span>
Sample Demo on StackBlitz
Followed steps in AngularFire Quickstart
Add authentication as described in 5. Getting started with Firebase Authentication
When I set my Firestore rules to limit read and write access to authenticated users, I either get an error or I get nothing. For more details, see Issue #2838 filed in the GitHub repository.
My environment is:
Angular CLI: 12.0.1
Node: 14.17.0
Package Manager: npm 7.13.0
AngularFire: 6.1.5
Firebase: 8.6.1
Firebase Tools: 9.11.0
OS: Ubuntu 20.04.2 LTS (linux x64)
My Firestore rules are:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read: if request.auth != null;
allow write: if request.auth != null;
}
}
}
app.component.ts
import { Component, OnInit } from '#angular/core';
import { AngularFirestore } from '#angular/fire/firestore';
import { AngularFireAuth } from '#angular/fire/auth';
import firebase from 'firebase/app';
import { Observable } from 'rxjs';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'Angular Fire Quickstart';
userDisplayName: string | null = null;
leagues$: Observable<any[]> = new Observable<any[]>();
constructor(
private firestore: AngularFirestore,
public auth: AngularFireAuth) {}
ngOnInit() {
// Recommended in Firebase documentation
this.auth.onAuthStateChanged((user) => {
if (user) {
this.userDisplayName = user.displayName;
this.leagues$ = this.firestore.collection('Leagues').valueChanges();
} else {
this.userDisplayName = null;
this.leagues$ = new Observable<any[]>();
}
});
}
login() {
this.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider());
}
logout() {
this.auth.signOut();
}
}
app.component.html
<div *ngIf="userDisplayName != null; else showLogin">
<p>Hello {{userDisplayName}}.
<button (click)="logout()">Logout</button>
</p>
<ul>
<li *ngFor="let league of leagues$ | async">
{{ league.name }} - {{ league.location }}
</li>
</ul>
</div>
<ng-template #showLogin>
<p>Please login.</p>
<button (click)="login()">Login</button>
</ng-template>
Resolved by subscribing to the Observable and changing my template to watch an array managed by the subscription. I now get data every time.
Here's the code with the changes:
app.component.ts
...
export class AppComponent implements OnInit {
title = 'Angular Fire Quickstart';
theUser: firebase.User | null = null;
leagueArray: Array<any> = []; // Eliminated the Observable in favor of an Array
constructor(
private firestore: AngularFirestore,
public auth: AngularFireAuth) {}
ngOnInit() {
this.auth.onAuthStateChanged((user) => {
if (user) {
this.theUser = user;
// Added the subscription and populated the array from there.
this.firestore.collection('Leagues').valueChanges().subscribe((data) => {
data.forEach((item) => {
this.leagueArray.push(item);
});
});
} else {
this.theUser = null;
this.leagueArray = [];
}
});
}
...
app.component.html
<div *ngIf="theUser != null">
<p>Hello {{theUser.displayName}}.
<button (click)="logout()">Logout</button>
</p>
<ul>
<!-- Watch the array instead of an Observable -->
<li *ngFor="let league of leagueArray">
{{ league.name }} - {{ league.location }}
</li>
</ul>
</div>
this is my first project with vue and nodejs so please let me know if I there is a missing information.
I'm trying to develop a group chat with Laravel, Vue js and Pusher.
Database Tables and Relations
I want to create a private Channel for each team which is available.
As soon as you click on the group chat, the existing messages get loaded and shown.
When you send a message, the message gets added to the messages table and is also sent successfully to pusher as you can see here:
Pusher message
The message is also added to the message list on the sender but not on the other team members.
Sender
Other team members
The new message is only shown on the other team members when they reload the page. That means that the echo listener doesn't seem to work. What can I do to fix it? What is wrong?
Here is my code:
ChatApp.vue (root component)
<template>
<div class="chat-container row">
<i class="far fa-comments fa-3x"></i>
<div id="chat-app" class="chat-app">
<div class="row mx-0 h-100 overflow-hidden">
<TeamList :teams="teamList" #selected="startConversationWith"/>
<Conversation :team="selectedTeam" :messages="messages" #new="saveNewMessage"/>
</div>
</div>
</div>
</template>
<script>
import MessageList from './MessageList';
import TeamList from './TeamList';
import Conversation from './Conversation';
import MessageTextBox from './MessageTextBox';
export default {
props: {
user: {
type: Object,
required: true
}
},
data() {
return {
messages: [],
teamList: [],
selectedTeam: null,
}
},
mounted() {
Echo.private('messages.1')
.listen('NewMessage', (e) => {
this.handleIncoming(e.message);
});
axios.get('/teams')
.then((response) => {
this.teamList = response.data;
});
},
methods: {
startConversationWith(team) {
axios.get('/conversation/' + team.id)
.then((response) => {
this.messages = response.data;
this.selectedTeam = team;
});
},
saveNewMessage(text) {
this.messages.push(text);
},
handleIncoming(message) {
this.saveNewMessage(message);
return;
}
},
components: {TeamList, MessageList, MessageTextBox, Conversation}
}
</script>
App/Events/NewMessage.php
<?php
namespace App\Events;
use App\Message;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class NewMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
/**
* Create a new event instance.
*
* #param Message $message
*/
public function __construct(Message $message)
{
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('messages.' . $this->message->team_id);
}
public function broadcastWith()
{
$this->message->load('team');
return ["message" => $this->message];
}
}
routes/channels.php
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('messages.{id}', function ($team_id, $message) {
return true;
// return (int) $team->id === (int) $id;
});
Message model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Message extends Model
{
protected $guarded = [];
public function team()
{
return $this->belongsTo('App\Team');
}
public function user()
{
return $this->belongsTo('App\User');
}
}
ContactsController
namespace App\Http\Controllers;
use App\Events\NewMessage;
use App\Message;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
class ContactsController extends Controller
{
public function getTeams() {
$teams = Auth::user()->teams;
return response()->json($teams);
}
public function getMessagesFor($id)
{
$messages = Message::where('team_id', $id)->get();
return response()->json($messages);
}
public function send(Request $request) {
$message = Message::create([
'team_id' => $request->team_id,
'user_id' => Auth::user()->id,
'message' => $request->text
]);
broadcast(new NewMessage($message));
return response()->json($message);
}
}
bootstrap.js
window._ = require('lodash');
/**
* We'll load jQuery and the Bootstrap jQuery plugin which provides support
* for JavaScript based Bootstrap features such as modals and tabs. This
* code may be modified to fit the specific needs of your application.
*/
try {
window.Popper = require('popper.js').default;
window.$ = window.jQuery = require('jquery');
require('bootstrap');
} catch (e) {}
/**
* We'll load the axios HTTP library which allows us to easily issue requests
* to our Laravel back-end. This library automatically handles sending the
* CSRF token as a header based on the value of the "XSRF" token cookie.
*/
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
/**
* Echo exposes an expressive API for subscribing to channels and listening
* for events that are broadcast by Laravel. Echo and event broadcasting
* allows your team to easily build robust real-time web applications.
*/
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
encrypted: true
});
encrypted is set to true for SSL config. Try setting it to false when configuring laravel echo in bootstrap.js
As you can see in the comments, setting encrypted to false in bootstrap.js solved the problem
I am rendering modal using react and redux.
I've seen thousand of examples of how to create a modal, but none on how to fire it inside another component.
I took the same approach to render modals on redux
on this question
My store is this:
export const store=createStore(
rootReducer,
compose(
applyMiddleware(thunk)
))
And the main component:
class Main extends React.Component {
render () {
return(
<BrowserRouter>
<Provider store={store} >
<App/>
</Provider>
</BrowserRouter>
)
}}
The app component is where I am guessing I should render the modal
class App extends React.Component {
render () {
return(
<div className="main-app">
<Home />
<Modal />
</div>
)
}}
But how can I update the state of this Modal component from within the components inside <Home >
My modal component looks like this:
import LoginModal from './LoginModal';
const MODAL_COMPONENTS = {
'LOGIN': LoginModal
}
class ModalRoot extends React.Component {
render() {
const SpecificModal = MODAL_COMPONENTS[this.props.modal.modalType];
if(!this.props.modal.showModal) return <SpecificModal />
return null
}
}
let mapStateToProps=state=>{
return {
modal: state.modal
}
}
export default connect(mapStateToProps)(ModalRoot);
Which will be the best approach to change the state three (store) of my redux app to change the state of the modal?
Thanks
Suppose you want to trigger the modal by clicking a button in Home button. You can pass in dispatch function to Home using mapDispatchToProps and dispatch action that changes the state of modal from there.
actions.js
function changeModal(payload) {
return {
type: 'CHANGE_MODAL',
payload,
}
}
reducer
// below defines what's in store.modal
function modalReducer(state = {}, action) {
switch(action.type) {
case: 'CHANGE_MODAL':
return {
...state,
...action.payload
}
// ... rest of your code
}
}
Home component
class Home extends Component {
//... rest of logic
changeModal = (modal) => {
const currentModal = {
showModal: true,
modalType: modal,
}
this.props.changeModal({ modal: currentModal });
}
render() {
// im using 2 buttons to trigger different modals,
return <div>
<button onClick={() => this.changeModal('HOME')}>trigger home modal</button>
<button onClick={() => this.changeModal('OTHER')}>trigger other modal</button>
</div>
}
}
const mapDispatchToProps = (dispatch) => ({
changeModal: (payload) => dispatch(changeModal(payload))
});
// insert mapDispatchToProps as a second argument to connect
// home component may or may not have mapStateToProps
export default connect(mapStateToProps, mapDispatchToProps)(Home);
So when you press the button, the state.modal will change and it will show the modal depending on the new state.
Typescript Error
Property 'isEnabled' does not exist on type 'typeof BluetoothSerial'
BluetoothSerial.isEnabled().then((data)=> {
and also here
BluetoothSerial.list().then((allDevices) => {
Above is the error i get at runtime in ionic 2.
Thank you.
I think it isn't working because a browser can't detect bluetooth devices try running the app on an actual device. Then use chrome://inspect through USB debugging to view the logs.
So i edited your code and its working. This is it. It shows paired devices not discovered devices.
import {Component} from '#angular/core';
import {AlertController, NavController} from 'ionic-angular';
import {BluetoothSerial} from '#ionic-native/bluetooth-serial';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public deviceList:any;
constructor(public navCtrl: NavController,
private alertCtrl:AlertController,
private bluetoothSerial: BluetoothSerial) {
this.getAllBluetoothDevices();
}
// put BluetoothSerial inside a function, can't be called different
getAllBluetoothDevices() {
// async so keep everything in this method
this.bluetoothSerial.isEnabled().then(data => {
if(data){
this.bluetoothSerial.list().then(allDevices=> {
// set the list to returned value
if(allDevices.length > 0){
this.deviceList=allDevices;
}else{
let alert = this.alertCtrl.create({
title: 'Bluetooth',
subTitle: 'No devices found.',
buttons: ['Dismiss']
});
alert.present();
}
});
}
}).catch(err=>{
let alert = this.alertCtrl.create({
title: 'Bluetooth',
subTitle: 'Check your bluetooth connection.',
buttons: ['Dismiss']
});
alert.present();
});
}
}
I solve the problem any how but yet i am not getting the error as above,
but now i am not getting the console.log("lists").
Can anyone say that code is running or not??
Because i am not getting any error but also not getting console log .
import { Component } from '#angular/core';
import { BluetoothSerial } from '#ionic-native/bluetooth-serial';
import { NavController } from 'ionic-angular';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public working:string;
public var2: string ;
public lists = [];
public bluetoothSerial: BluetoothSerial;
constructor(public navCtrl: NavController ) {
let me = this;
me.getAllBluetoothDevices();
}
// put BluetoothSerial inside a function, can't be called different
getAllBluetoothDevices(){
let me = this;
// async so keep everything in this method
me.bluetoothSerial.isEnabled().then((data)=> {
// not sure of returning value, probably a boolean
console.log("dont know what it returns"+data);
// returns all the available devices, not just the unpaired ones
me.bluetoothSerial.list().then((allDevices) => {
// set the list to returned value
me.lists = allDevices;
console.log("lists");
if(me.lists.length == 0){
me.var2 = "could not find any bluetooth devices";
console.log("lists");
}
});
});
}
}