Conversation chat cannot submit - javascript

I have problem when make submit chat its have error 'handlebar is not define'. I follow tutorial code in this link : https://codepen.io/drehimself/pen/KdXwxR
this is the error :
here my html code :
<div class="chat-area scrollbar-macosx scroll-wrapper">
<div class="chat-area-content scrollbar-macosx">
<ul class="container">
<!-- Label Time Chat -->
<div class="text-center mt-3">
<span class="label-time">30 Apr</span>
</div>
<!-- Merchant chat -->
<div class="d-flex justify-content-start mt-3">
<div class="chat-content-image">
<div class="upload-image">
<div class="time-image">
<span class="time-item">14:10</span>
</div>
</div>
</div>
</div>
<!-- Customer chat -->
<div class="d-flex justify-content-start mt-3">
<div class="chat-context">
<div class="chat-text">
<p></p>
</div>
<div class="chat-time">
<p>14:15</p>
</div>
</div>
</div>
<!-- Customer Chat -->
<div class="d-flex justify-content-end mt-3 mb-4">
<div class="chat-context">
<div class="chat-text">
<p></p>
</div>
<div class="chat-time">
<p>15:00</p>
</div>
</div>
</div>
</ul>
</div>
<form class="keyboard-chat">
<div class="chat-input">
<div class="attach-button mr-3 mb-3">
<button type="button" class="circle-button">
<i class="fa fa-plus"></i>
</button>
</div>
<div class="chat-input-textarea" style="padding-left: 0px;">
<div>
<textarea id="message-to-send" name="message-to-send" placeholder="Type here..." rows="3" class="keyboards f-size-12" style="max-height: 130px;"></textarea>
</div>
</div>
<div class="btn-submit-message mb-3"></div>
</div>
</form>
</div>
<script id="message-template" type="text/x-handlebars-template">
<div class="d-flex justify-content-end mt-3">
<div class="chat-context">
<div class="chat-text">
<p>{{messageOutput}}</p>
</div>
<div class="chat-time">
<p>{{time}}</p>
</div>
</div>
</div>
</script>
And here my js :
(function(){
var chat = {
messageToSend: '',
messageResponses: [
'Why did the web developer leave the restaurant? Because of the table layout.',
'How do you comfort a JavaScript bug? You console it.',
'An SQL query enters a bar, approaches two tables and asks: "May I join you?"',
'What is the most used language in programming? Profanity.',
'What is the object-oriented way to become wealthy? Inheritance.',
'An SEO expert walks into a bar, bars, pub, tavern, public house, Irish pub, drinks, beer, alcohol'
],
init: function() {
this.cacheDOM();
this.bindEvents();
this.render();
},
cacheDOM: function() {
this.$chatHistory = $('.chat-area-content');
this.$button = $('.btn-submit-message');
this.$textarea = $('#message-to-send');
this.$chatHistoryList = this.$chatHistory.find('ul');
},
bindEvents: function() {
this.$button.on('click', this.addMessage.bind(this));
this.$textarea.on('keyup', this.addMessageEnter.bind(this));
},
render: function() {
this.scrollToBottom();
if (this.messageToSend.trim() !== '') {
var template = Handlebars.compile( $("#message-template").html());
var context = {
messageOutput: this.messageToSend,
time: this.getCurrentTime()
};
this.$chatHistoryList.append(template(context));
this.scrollToBottom();
this.$textarea.val('');
// responses
var templateResponse = Handlebars.compile( $("#message-response-template").html());
var contextResponse = {
response: this.getRandomItem(this.messageResponses),
time: this.getCurrentTime()
};
setTimeout(function() {
this.$chatHistoryList.append(templateResponse(contextResponse));
this.scrollToBottom();
}.bind(this), 1500);
}
},
addMessage: function() {
this.messageToSend = this.$textarea.val()
this.render();
},
addMessageEnter: function(event) {
// enter was pressed
if (event.keyCode === 13) {
this.addMessage();
}
},
scrollToBottom: function() {
this.$chatHistory.scrollTop(this.$chatHistory[0].scrollHeight);
},
getCurrentTime: function() {
return new Date().toLocaleTimeString().
replace(/([\d]+:[\d]{2})(:[\d]{2})(.*)/, "$1$3");
},
getRandomItem: function(arr) {
return arr[Math.floor(Math.random()*arr.length)];
}
};
chat.init();
})();
Code of .js same like in the tutorial, but i only change the name class i used.
My Expectation is when i enter / click button send, the conversation is submited to the chat area.

This code requires Handlebars JS since you call Handlebars. You can it install it by follwing the installation steps on the website.

Related

Vue Laravel: Reactive Nested Array value is Empty on Backend

I'm relatively new to Vue JS. So I have this case on Form Submit.
This is what I've submitted in Console Log:
{
amount: [
monday: "123",
tuesday: "97438"
],
day_of_week: "perday",
started_at: "2022-09-14"
}
And what it received in Laravel Backend when I dump the data is this:
^ array:3 [
"started_at" => "2022-09-14"
"day_of_week" => "perday"
"amount" => []
]
So My Question Is, what did I do wrong? How is the "amount" part not included on the backend? It already looks right on the console.log. I do appreciate help here. I reckon I did a mistake on how to write the model name in the array part inside HTML, but still, I do not know how to do it right.
THANK YOU IN ADVANCE πŸ™πŸΌπŸ™πŸΌπŸ™πŸΌ
This is how I submit my form:
HTML Vue Page:
<div class="card-body p-9">
<div class="row mb-8">
<div class="col-xl-3">
<div class="fs-6 fw-semibold mt-2 mb-3">Type of Rate</div>
</div
<div class="col-xl-9 fv-row">
<VueMultiselect v-model="day_of_week" label="name" track-by="name" placeholder="Select Type" :options="type_of_day" :close-on-select="true">
<template slot="singleLabel" slot-scope="{ type_of_day }"><strong>{{ type_of_day.name }}</strong></template>
</VueMultiselect>
</div>
</div>
<div class="row mb-8">
<div class="col-xl-3">
<div class="fs-6 fw-semibold mt-2 mb-3">Started Date</div>
</div
<div class="col-xl-9 fv-row">
<div class="position-relative d-flex align-items-center">
<input v-model="ticketing.started_at" class="form-control form-control-solid ps-12" name="date" placeholder="Pick Start date" id="kt_datepicker_1" />
</div>
</div>
</div>
<div v-if="day_of_week">
<div v-if="day_of_week.value == 'allday'" class="row mb-8">
<div class="col-xl-3">
<div class="fs-6 fw-semibold mt-2 mb-3">Entrance Rate</div>
</div>
<div class="col-xl-9 fv-row">
<div class="input-group mb-5">
<span class="input-group-text">Rp.</span>
<input v-model="amount.allday" type="text" class="form-control" aria-label="Amount"/>
</div>
</div>
</div>
<div v-if="day_of_week.value == 'perday'" class="row mb-8">
<div class="col-12 mb-8">
<div class="fs-6 fw-bold mt-2 mb-3">Entrance Rate Per Day of Week</div>
</div>
<div class="col-xl-3">
<div class="fs-6 fw-semibold mt-2 mb-3">Monday</div>
</div>
<div class="col-xl-9 fv-row">
<div class="input-group mb-5">
<span class="input-group-text">Rp.</span>
<input v-model="amount.day.monday" type="text" class="form-control" aria-label="Amount"/>
</div>
</div>
<div class="col-xl-3">
<div class="fs-6 fw-semibold mt-2 mb-3">Tuesday</div>
</div>
<div class="col-xl-9 fv-row">
<div class="input-group mb-5">
<span class="input-group-text">Rp.</span>
<input v-model="amount.day.tuesday" type="text" class="form-control" aria-label="Amount"/>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer d-flex justify-content-end pb-6 px-9">
<span #click="storeNewRate" class="btn btn-primary">Create New Rate</span>
</div>
</template>
This Is the script Part
<script>
import { onMounted, toRaw } from "vue";
import useTicketing from "../../../composable/ticketing";
export default {
data() {
const { storeTicketing, ticketing } = useTicketing()
const storeNewRate = async () => {
let type = this.day_of_week.value
let submittedAmount = []
type == 'allday' ? submittedAmount = this.amount.allday : submittedAmount = this.amount.day
this.ticketing.day_of_week = this.day_of_week.value
this.ticketing.amount = submittedAmount
console.log('submit: ', toRaw(ticketing))
await storeTicketing({...ticketing})
}
return {
type_of_day: [
{
"name": "All Days of Week",
"value": "allday"
},
{
"name": "Rate per Day",
"value": "perday"
},
],
started_at: '',
day_of_week: '',
amount: {
allday: '',
day: []
},
storeNewRate,
ticketing
}
}
}
</script>
And I have Separate file for handling the API:
export default function usePlan() {
const ticketing = reactive({});
const router = useRouter();
let toastr = Swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 5000
})
const storeTicketing = async (data) => {
let errors = ''
try {
let response = await axios.post('/api/ticketing/create', data);
ticketing.value = response.data;
await toastr.fire("Success", "New Rate Has Been Created!", "success");
} catch (e) {
if(e.response.status === 422) {
for(const key in e.response.data.message) {
errors = e.response.data.message[key][0];
toastr.fire("Failed", errors, "error");
}
errors = ''
}
}
}
return {
storeTicketing,
ticketing
}
}
πŸ™πŸΌ

JQUERY JSON FORM API LIVE SEARCH

I'm trying to make live search with Jquery with the data from API, but i have some problem:
The suggestion still appear even the search box si empty
When i bluring the search box the suggestion search still appear
I can't submit the form with pressing the enter button, i must click the button on the from
$(document).ready(function() {
let api = "https://corona.lmao.ninja/v2/countries/";
$("#search").keyup( function() {
$("#result").html('');
let searchField = $("#search").val();
let expression = new RegExp( searchField, "i" );
$.getJSON( api, function( data ) {
$.each( data, function( key, value ) {
if( value.country.search(expression) != -1 /*|| value.continent.search(expression) */ )
{
$("#result").append(`<li class="list-group-item c">${value.country} <img src="${value.countryInfo.flag}" class="img-thumbnail"></li>`)
}
} );
} );
} );
$("#result").on("click", "li", function() {
$("#search").val($(this).text());
$("#result").html('');
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row py-4">
<div class="search__wrapper col-12 text-center text-center">
<form id="covidSearch">
<i class="fw-bolder text-center fs-6 font-monospace">API by <a target="_blank" class="link-dark" href="https://corona.lmao.ninja/v2/countries/">disease.sh</a></i>
<h4>Search by Country</h4>
<input type="text" name="search" id="search" placeholder="Country Name" class="text-muted fs-6">
<button type="submit" class="fw-bold text-white">Search</button> <br>
<!-- LOADING ANIMATION WILL BE HERE -->
</form>
<!-- LIVE SEARCH SUGGESTION -->
<ul class="list-group text-center fw-bolder suggestionSearch" id="result"></ul>
</div>
</div>

How to read data from a v-for (vue.js)?

Given the next v-for:
<div class="container-fluid" id="networdapp" style="display:none;">
<div class="row" >
<div v-for="result in results" class="col-sm-6" >
<div class="card m-3 h-240 bg-light" >
<div class="card-header text-center" > {{ result.title }} </div>
<div class="card-body" style="height:200px" >
<p class="card-text" v-html="result.prevDesc"></p>
</div>
<div class="card-footer bg-transparent border-info">
<a href="/details" class="btn btn-info" #click="getData(result)" >Details</a>
</div>
</div>
</div>
</div>
</div>
And the next Vue.js script:
<script type="text/javascript">
const vm = new Vue({
el: '#networdapp',
data: {
results:[]
},
methods: {
getData: function(result){
window.alert($(this).parents("#networdapp").find(".card-header.text-center").outerHTML);
window.alert(document.getElementsByClassName("card-header").outerHTML);
window.alert(result.outerHTML);
}
},
mounted() {
axios.get('/getJson')
.then(response => {
this.results = response.data;
})
.catch( e => {
console.log(e);
});
}
});
</script>
I want to get data from a specific iteration,let's say if I click the "Details" button of the 3rd div from the v-for I want to get the {{result.title }} data from the 3rd for.Is it possible?I've been reading the Vue.js documentation but I didn't find anything about reading the data from DOM.If it is not possible,than how can I do that without Vue.js?Is there any other option?
The main goal is to get this data and to put it into a js object passing it to another webpage.
you have to pass index key and use is to get from results's position.
change the for loop div into
<div v-for="(result,i) in results" :key="i" class="col-sm-6" >
also chnange the methods parameter
<a href="/details" class="btn btn-info" #click="getData(i)" >Details</a>
and the method will get the index key and here i have used console to see the result.title that you have wanted. you can use it any how you want.
getData: function(key){
console.log(this.results[key].title)
}
so
Given the next v-for:
<div class="container-fluid" id="networdapp" style="display:none;">
<div class="row" >
<div v-for="(result,i) in results" :key="i" class="col-sm-6" >
<div class="card m-3 h-240 bg-light" >
<div class="card-header text-center" > {{ result.title }} </div>
<div class="card-body" style="height:200px" >
<p class="card-text" v-html="result.prevDesc"></p>
</div>
<div class="card-footer bg-transparent border-info">
<a href="/details" class="btn btn-info" #click="getData(i)" >Details</a>
</div>
</div>
</div>
</div>
And the next Vue.js script:
<script type="text/javascript">
const vm = new Vue({
el: '#networdapp',
data: {
results:[]
},
methods: {
getData: function(key){
console.log(this.results[key].title)
}
},
mounted() {
axios.get('/getJson')
.then(response => {
this.results = response.data;
})
.catch( e => {
console.log(e);
});
}
});
To get the data you want to access in the results array, you can use an index in your v-for loop
v-for="(result, index) in results"
you can check the docs here https://v2.vuejs.org/v2/guide/list.html
I also strongly recommend you to add a key attribute after the v-for to help vue.js
keep track of each result, see https://v2.vuejs.org/v2/guide/list.html#key

What should be an ideal place for listening events pushed from server in react?

hope you're all doing great, I was just curious to know what could be an ideal place for listening events pushed from server, I'm playing with socket-io and trying to make a chat application in which the server pushes messages to the client, here is the code
getInitialState:function(){
return {localstatemessages: ['hi'],remoteuserstatemessages:['hello']}},
render: function () {
this.ListenEvents();
var localusermsgs=this.state.localstatemessages.map(function(Message){
return(
<SendMessage Message={Message}/>
)
});
var recievedmsgs=this.state.remoteuserstatemessages.map(function(msg){
return(
<RecievedMessage Message={msg} />
)
})
return (
<div className="col-lg-8 col-md-8 col-xs-8 pull-right">
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div className="row">
<div className="page-header">
<div className="media">
<div className="media-left">
<img src={require("../_assets/_images/download.jpeg")} className="img-circle" alt="user image" />
</div>
<div className="media-body">
<h2 className="media-heading">peer user</h2>
</div>
<div className="media-right"></div>
</div>
</div>
</div>
</div>
<div className="chat_box">
<RecievedMessage Message={this.state.remoteusermsg}/>
<SendMessage Message={this.state.usermsg}/>
</div>
<div className="msg_area">
<div className="row">
<div className="col-lg-12">
<div className="input-group">
<textarea type="text" cols="5" rows="2" onKeyDown={this.sendMessage} className="form-control" placeholder="Type here..."></textarea>
<span className="input-group-btn">
<button className="btn btn-warning" type="button" onClick={this.sendMessage}>send</button>
</span>
</div>
</div>
</div>
</div>
</div>
)
},
sendMessage: function (event) {
if (event.keyCode == 13) {
let target = event.target;
var msg = target.value;
// alert('message is: ' + msg);
//event raising through ajax goes here
socket.emit('chat mssg',msg);
// alert('pushing msg ');
var newlocalmsg= this.state.localstatemessages;
newlocalmsg.push(msg);
this.setState({localstatemessages:newlocalmsg});
target.value='';
}
},
handleRemoteMesssageUpdate:function(message){
var remotemessages=this.state.remoteuserstatemessages;
remotemessages.push(message);
this.setState({remoteuserstatemessages:remotemessages})
},
ListenEvents:function(){
socket.on('chat mssg',function (msg){
// alert('pushing anothermsg');
this.handleRemoteMesssageUpdate(msg);
}.bind(this));
}
});
module.exports = ChatBox;here
the state remoteuserstatemessages updates three times for a single pushed events , i don't understand what is going on here, does the render function calls the ListenEvents repetitively ? how can it be done?
You put this.ListenEvents() in render(), of course it will be called for many times.
Since you are using socket, you just need to intialize the connection once right? So better you call it in componentWillMount()
componentWillMount(){
this.ListenEvents()
}
render(){
// render code
}
More about React Component Lifecycle : https://facebook.github.io/react/docs/react-component.html

Isolate just the element that was clicked

I'm just getting started with Angular and running up against some roadblocks in my understanding of certain core concepts. To better familiarize myself with this new framework I'm attempting to build a trivial application: "Would You Rather?". I present the user two questions, they pick one, I highlight their choice, and show how many votes each question has from previous users.
It sounds simple but I'm still stuck in a jQuery frame of mind; I want to select the element based on $(this) or $("#id").
I have a factory with an array of question objects. Each object has a firstQuestion and secondQuestion key that maps to a question, as well as a firstVotes and secondVotes key with the corresponding number of votes. I'm using a QuestionsCtrl to control scope and take action when a user makes a choice.
Here's my index.html file:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="utf-8">
<title>Would You Rather?</title>
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div class="container" ng-app="wouldYouRatherApp">
<div ng-controller="QuestionsCtrl">
<div class="container">
<div class="row text-center">
<h1 class="col-md-12">Would you rather...</h1>
</div>
<div class="row text-center">
<div class="col-md-12">
<h2 class="btn btn-lg btn-{{buttonClass}}" ng-click="recordAnswer('first')">{{question.firstQuestion}}</h2>
<span class="badge" ng-show="badge.show">{{question.firstVotes}}</span>
</div>
</div>
<div class="row text-center">
<h3 class="col-md-12"><small>or</small></h3>
</div>
<div class="row text-center">
<div class="col-md-12">
<h2 class="btn btn-lg btn-{{buttonClass}}" ng-click="recordAnswer('second')">{{question.secondQuestion}}</h2>
<span class="badge" ng-show="badge.show">{{question.secondVotes}}</span>
</div>
</div>
<br>
<div class="row text-center">
<div class="col-md-12">
<h2 class="btn btn-lg btn-primary" ng-show="showNextQuestion" ng-click="nextQuestion()">Next Question <span class="glyphicon glyphicon-forward"></span></h2>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js"></script>
<script type="text/javascript" src="./main.js"></script>
</body>
</html>
And here's my main.js file:
var app = angular.module("wouldYouRatherApp", []);
app.factory("Badges", function() {
return {show: false}
})
app.factory("Questions", function() {
var Questions = [{
firstQuestion: "Ride a horse?",
firstVotes: 101,
secondQuestion: "Ride a cowboy?",
secondVotes: 212
},
{
firstQuestion: "Kiss a frog?",
firstVotes: 13,
secondQuestion: "Lick a slug?",
secondVotes: 23
},
{
firstQuestion: "Play Monopoly?",
firstVotes: 12,
secondQuestion: "Play Risk?",
secondVotes: 17
}];
return Questions;
})
app.controller("QuestionsCtrl", function($scope, Badges, Questions) {
$scope.question = Questions.shift();
$scope.buttonClass = 'default';
$scope.showNextQuestion = false;
$scope.badge = Badges;
$scope.recordAnswer = function(choice) {
console.log("User chose: " + choice);
$scope.buttonClass = 'success';
// increment votes badge
$scope[choice+'Votes'] += 1;
Badges.show = true;
$scope.showNextQuestion = true;
}
$scope.nextQuestion = function() {
$scope.question = Questions.shift();
Badges.show = false;
$scope.buttonClass = 'default';
$scope.showNextQuestion = false;
}
})
A live example can be found here: http://jsfiddle.net/t99TL/2/
The app's expected behavior is as follows:
Two questions are presented to the user.
The user clicks on one of the buttons.
That question is highlighted. And the votes badge is incremented. Both votes badges are displayed.
A 'Next Question' button is presented to the user.
When he/she clicks on the 'Next Question' button, a new question is loaded.
I feel like I probably need to create a directive for each individual question... but I'm not sure how to start, or if I'm even on the right path. Any advice on obstacles I'm going to face further down the line is much appreciated (i.e. Updating the votes attribute for the question, etc.).
There are a lot to change to make it work the way you want. This code is not perfect, just a demonstration.
HTML:
<div class="container" ng-app="wouldYouRatherApp">
<div ng-controller="QuestionsCtrl">
<div class="container">
<div class="row text-center">
<h1 class="col-md-12">Would you rather...</h1>
</div>
<div class="row text-center">
<div class="col-md-12">
<h2 class="btn btn-lg btn-{{question.firstQuestion.buttonClass}}" ng-click="recordAnswer(question.firstQuestion)">{{question.firstQuestion.text}}</h2>
<span class="badge" ng-show="badge.show">{{question.firstQuestion.votes}}</span>
</div>
</div>
<div class="row text-center">
<h3 class="col-md-12"><small>or</small></h3>
</div>
<div class="row text-center">
<div class="col-md-12">
<h2 class="btn btn-lg btn-{{question.secondQuestion.buttonClass}}" ng-click="recordAnswer(question.secondQuestion)">{{question.secondQuestion.text}}</h2>
<span class="badge" ng-show="badge.show">{{question.secondQuestion.votes}}</span>
</div>
</div>
<br>
<div class="row text-center">
<div class="col-md-12">
<h2 class="btn btn-lg btn-primary" ng-show="showNextQuestion" ng-click="nextQuestion()">Next Question <span class="glyphicon glyphicon-forward"></span></h2>
</div>
</div>
</div>
</div>
JS:
var app = angular.module("wouldYouRatherApp", []);
app.factory("Badges", function() {
return {show: false}
})
app.factory("Questions", function() {
var Questions = [{
firstQuestion: {
text:"Ride a horse?",
votes: 101,
buttonClass : 'default'
},
secondQuestion: {
text:"Ride a cowboy?",
votes: 212,
buttonClass : 'default'
},
},
{
firstQuestion: {
text:"Kiss a frog?",
votes: 13,
buttonClass : 'default'
},
secondQuestion: {
text:"Lick a slug?",
votes: 23,
buttonClass : 'default'
}
},
{
firstQuestion: {
text:"Play Monopoly?",
votes: 12,
buttonClass : 'default'
},
secondQuestion: {
text:"Play Risk?",
votes: 17,
buttonClass : 'default'
}
}];
return Questions;
})
app.controller("QuestionsCtrl", function($scope, Badges, Questions) {
$scope.question = Questions.shift();
$scope.buttonClass = 'default';
$scope.showNextQuestion = false;
$scope.badge = Badges;
$scope.recordAnswer = function(choice) {
choice.buttonClass = 'success';
choice.votes++;
Badges.show = true;
$scope.showNextQuestion = true;
}
$scope.nextQuestion = function() {
$scope.question.firstQuestion.buttonClass = "default";
$scope.question.secondQuestion.buttonClass = "default";
$scope.question = Questions.shift();
Badges.show = false;
$scope.showNextQuestion = false;
}
})
DEMO

Categories

Resources