How to trigger a React click event with Web Component - web

I have rendered ReactComponent with WebComponent but component click event does not trigger
Is there a way to trigger ReactComponent events rendered by WebComponent?
A simple React component
const event = () => {
console.log('aaaaaa');
}
export const Component = ({message}) => {
return (
<button type={'button'} onClick={event}> {message} </button>
)
};
Call it in the WebComponent rendering
export class ConfirmButton extends HTMLElement {
connectedCallback() {
const parent = document.createElement('div');
const message = this.getAttribute('message');
this.attachShadow({ mode: 'open' }).appendChild(parent);
ReactDOM.render(<Component message={message} />, parent);
}
}
By assumption, "aaaa" should be displayed on the console when the button is clicked.
However, no results are displayed ...

Related

Laravel Echo listener is not listening

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

Access component state when user is going to previous scene

react-native-router-flux version: 3.39.1
Hi, i need to access to component state when the user clicks on Back button of navbar to go to previous scene .
Is there a way of doing this ?
i need this to verify the state if the user did some working on any textInput.
https://github.com/aksonov/react-native-router-flux/issues/647
If you use the "cheat" that jo-asakura says, you be able to access component state onBack button :)
// your scene
<Scene key="someKey"
component={ SomeComponent }
onRight={
(state) => {
// state.scene.navigationState.myData is { hello: 'world' }
}
} />
// your component
class SomeComponent extends Component {
// ...
handleButtonClick() {
this.props.navigationState.myData = { hello: 'world' };
}
// ...
}
PS: in my case i have put this line at render function to always save new data.
render(){
this.props.navigationState.myData = this.state;
return()
}

Rendering modal on click (user action) react redux

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.

Material-ui example

I got this code snippet from Material-ui(Simple example) website itself and it seems it doesn't work immediately by just copying and paste directly.
It throws an error Unexpected token ("line#") while parsing, particularly in the handleChange = ....... . I'm currently using Visual Studio Code and i'm also new to using Material-ui in JSX.
What am i missing? Please help.
import React from 'react';
import DropDownMenu from 'material-ui/lib/DropDownMenu';
import MenuItem from 'material-ui/lib/menus/menu-item';
export default class DropDownMenuSimpleExample extends React.Component {
constructor(props) {
super(props);
this.state = {value: 2};
}
handleChange = (event, index, value) => this.setState({value});
render() {
return (
<DropDownMenu value={this.state.value} onChange={this.handleChange}>
<MenuItem value={1} primaryText="Never"/>
<MenuItem value={2} primaryText="Every Night"/>
<MenuItem value={3} primaryText="Weeknights"/>
<MenuItem value={4} primaryText="Weekends"/>
<MenuItem value={5} primaryText="Weekly"/>
</DropDownMenu>
);
}
}
Change handleChange = (event, index, value) => this.setState({value}); to
handleChange(event, index, value) {
this.setState({value})
};

open a MVC4 view inside a jquery Dialog

I want to take a view and instead of opening a new page I want to just open that view inside a Jquery dialog. I was just wondering how it's done or if possible.
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Jquery_Dialog.Models;
using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;
namespace Jquery_Dialog.Controllers
{
public class HomeController : Controller
{
private IEnumerable<Product> Products
{
get
{
return new List<Product>
{
new Product {ProductID = 1, Name = "Train", Category = "Toy", Price = 29.99M},
new Product {ProductID = 2, Name = "Truck", Category = "Toy", Price = 19.99M},
new Product {ProductID = 3, Name = "Bread", Category = "Food", Price = 2.49M},
new Product {ProductID = 4, Name = "Cookies", Category = "Food", Price = 2.99M}
};
}
}
public ActionResult Index()
{
IEnumerable<Product> productList = Products;
return View(productList);
}
public ActionResult Details(int id)
{
Product model = Products.Where(p => p.ProductID == id).SingleOrDefault();
return Request.IsAjaxRequest() ? PartialView(model) : PartialView(model);
}
public ActionResult About()
{
ViewBag.Message = "Your app description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
}
Index.cshtml
#model IEnumerable<Jquery_Dialog.Models.Product>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.9.1/themes/base/jquery-ui.css " />
<script src="http://code.jquery.com/jquery-1.8.2.js "></script>
<script src="http://code.jquery.com/ui/1.9.1/jquery-ui.js "></script>
<table> #foreach (var item in Model) {
<tr>
<td>
#Html.ActionLink(item.Name, "Details", new { id = item.ProductID }, new { #class = "ajax-details" })
</td>
</tr>
}
</table>
<div id="dialog" title="Title of dialog">
<p>This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.</p>
</div>
<script>
$(function () {
$('.ajax-details').on('click', function (e) { // bind to click event
// go get the page using the link's `href`
$.get($(this).prop('href'), function (response) {
$(response).dialog(); // take the response and throw it up in a dialog
// optional: Use jQuery UI's options to specify buttons and other
// settings here as well. It's also probably a good idea to
// bind the close event and $().remove() this element from
// the page on close since the user can click links over and
// over. (prevent DOM overload of hidden elements)
});
e.preventDefault(); // don't let it continue on
});
});
</script>
<script>
$("#dialog").dialog();
</script>
As you can see I have a simple dialog that opens a div but I want to be able to open the details view instead of clicking the ActionLink and going to a different page, I want to be able to click the ActionLink and have it open up in the dialog.
Assuming you make the ActionLink a little more accessible (by using a class name for instance):
#Html.ActionLink(item.Name, "Details", new { id = item.ProductID },
/* htmlAttributes: */ new { #class = "ajax-details" })
You also make a modification to the action so we can fetch partial contents when it's an ajax request:
public ActionResult Details(int id)
{
// this is another way of making sure that AJAX calls get partial content,
// but a normal visit would render the entire page.
return Request.IsAjaxRequest() ? PartialView(model) : View(model);
}
Optional You could also adjust your _ViewStart.cshtml file to do the same if this was common place on the website to render partial views/ajax supplementing:
#{
Layout = IsAjax ? null : "~/Views/Shared/_Layout.cshtml";
}
Now, we wire it up with AJAX. Again, reference the class name we game the link earlier (ajax-details):
$('.ajax-details').on('click',function(e){ // bind to click event
// go get the page using the link's `href`
$.get($(this).prop('href'), function(response){
$(response).dialog(); // take the response and throw it up in a dialog
// optional: Use jQuery UI's options to specify buttons and other
// settings here as well. It's also probably a good idea to
// bind the close event and $().remove() this element from
// the page on close since the user can click links over and
// over. (prevent DOM overload of hidden elements)
});
e.preventDefault(); // don't let it continue on
});
Don't have the opportunity to test it, but should get you in the ball park. if it doesn't get you close enough, let me know and I'll revisit the answer and adjust.

Resources