I'm trying to render msg from all_msgs array.
<script>
import { sender_msgs } from "../var_store";
import { receiver_msgs } from "../var_store";
const all_msgs = [1,2,3,4];
// $: msgs = all_msgs;
sender_msgs.subscribe((e) => {
all_msgs.push(`Sender: ${e.slice(-1)[0]}`);
});
receiver_msgs.subscribe((e) => {
all_msgs.push(`Receiver: ${e.slice(-1)[0]}`);
console.log(all_msgs);
});
</script>
<div class="chat-window">
{#each all_msgs as msg}
<div>{msg}</div>
{/each}
</div>
<style>
.chat-window {
width: 500px;
border: 1px solid #000;
}
</style>
I can see the numbers can be rendered as html text. But couldn't render other texts when all_msgs is updated by the two subscribe methods. I can see all_msgs in the console having the texts but can't be seen in html. The o/p of the screen and console.log of all_msgs is also shared.
Solved it: reactivity is assignment based. Below code works:
<script>
import { sender_msgs } from "../var_store";
import { receiver_msgs } from "../var_store";
let all_msgs = [];
// $: msgs = all_msgs;
sender_msgs.subscribe((e) => {
all_msgs.push(`Sender: ${e.slice(-1)[0]}`);
all_msgs = all_msgs;
});
receiver_msgs.subscribe((e) => {
all_msgs.push(`Receiver: ${e.slice(-1)[0]}`);
all_msgs = all_msgs;
});
</script>
<div class="chat-window">
{#each all_msgs as msg}
<div>{msg}</div>
{/each}
</div>
<style>
.chat-window {
width: 500px;
border: 1px solid #000;
}
</style>
Related
I am working on a real estate site and would like to have specific pages to show properties for rent/sale. I am trying to only show properties that have the "Rent" status, but the if statement seems to just default to else.
Using border styles to visibly see if statements.
web page: http://targetrealtygroupdev.com/rent/
What am I missing?
<div class="property-item">
<div class="proprty-inner>
<div class="property-status-bg">
"Rent"
</div>
</div>
</div>
.one {
border: 1px solid red;
}
.two {
border: 1px solid blue;
}
<script>
document.addEventListener("DOMContentLoaded", function(event) {
var status = document.getElementsByClassName("property-status-bg");
for (item of status) {
var type = item.innerText;
if (type == 'Rent') {
jQuery('.property-item').addClass('one');
} else {
jQuery('.property-item').addClass('two');
}
}
});
</script>
you are changing all jQuery('.property-item') for each item
and .property-status-bg is not only with a simple text == 'Rent' or 'Sale' ...
it's look like:
<p>
<span class="property-status-bg" style="background-color: #888">
Rent
<span class="property-arrow" style="border-left-color: #888; border-right-color: #888"></span>
</span>
</p>
So you have to use the string.include method
try:
document.addEventListener("DOMContentLoaded", function(event)
{
document.querySelectorAll('.property-status-bg').forEach(item =>
{
let ClassChoice = item.textContent.includes('Rent') ? 'one' : 'two'
item.closest('.property-item').classList.add( ClassChoice )
})
})
You are selecting all the elements, you are not selecting the one you are referencing in the loop.
item.closest('.property-item').classList.add('one');
I am working on a bookmark "collector" app that allows users save websites urls as a collection. I have created an array collectX in the localstorage to save each collections. However I am trying to edit and update each collections that have created on another HTML page.
How can I do that?
Here is what I have tried so far:
//get form values
// create an object of the form values
//create an empty array
//append object of the form values to the empty array
//display array object values
showCollection();
var getButton = document.getElementById('clickIt');
var collectionTitle = document.getElementById("title");
var collectionDescription = document.getElementById('describe')
getButton.addEventListener('click', function(e){
e.preventDefault()
var collections = {
title: collectionTitle.value,
description: collectionDescription.value,
collectedWebsites:[]
}
let webCollections = localStorage.getItem('collectx');
if(webCollections == null){
var collectionObj = []
alert('storage is empty')
}
else{
collectionObj = JSON.parse(webCollections);
}
collectionObj.push(collections);
localStorage.setItem("collectx", JSON.stringify(collectionObj));
showCollection()
});
function showCollection(){
let webCollections = localStorage.getItem('collectx')
if(webCollections == null){
var collectionObj = []
alert('storage is empty')
}
else{
collectionObj = JSON.parse(webCollections);
}
let html= ''
var demos = document.getElementById('demo');
collectionObj.forEach(function(item, index){
html += `<div class="collects">
Title: ${item.title} <br>
Description: ${item.description} </div>`
})
demos.innerHTML = html
}
body{
background-color: #000;
}
.collects{
width: 150px;
height: 100px;
padding: 10px 5px 10px 5px;
margin-right: 20px;
border-radius: 10px;
display: inline-block;
background-color: #fff;
}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CollectX</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<form id="forms">
<input id="title" type="text" placeholder="Collection name">
<br>
<br>
<input id="describe" type="text" placeholder="Description">
<button id="clickIt"> Submit </button>
</form>
<div id="demo">
</div>
<script src="/script.js"></script>
</body>
</html>
Here is the link to the JSFiddle: https://jsfiddle.net/c3jgezwr/2/
P.S: I have tried to the method used on this page: https://www.xul.fr/javascript/parameters.php
Please take a look to this example
CSS
body {
background-color: #000;
}
.collects {
min-width: 150px;
min-height: 100px;
padding: 10px 5px 10px 5px;
margin-right: 20px;
border-radius: 10px;
display: inline-block;
background-color: #fff;
overflow: hidden;
}
HTML
<form name="form">
<div>
<input name="title" placeholder="Title" />
</div>
<div>
<input name="describe" placeholder="Describe" />
</div>
<div>
<input name="links" placeholder="Add links separated by coma" />
</div>
<div>
<button type="submit">Submit</button>
</div>
</form>
JS
const form = document.forms.form;
form.addEventListener("submit", submitHandler);
function getData() {
return JSON.parse(localStorage.getItem("collectx")) ?? [];
}
function submitHandler(event) {
event.preventDefault();
const form = event.target;
const formData = new FormData(event.target);
const data = Object.fromEntries(formData);
const currentData = getData();
localStorage.setItem("collectx", JSON.stringify([...currentData, data]));
form.reset();
render();
}
function render() {
const collection = getData();
const entries = collection
.map(
({ title, describe, links }) => `
<div class="collects">
<p>Title: ${title}</p>
<p>Describe: ${describe}</p>
<p>Links: ${links && links
.split(",")
.map((link) => `${link}`)
.join("<br />")}
</p>
</div>`
)
.join("");
document.querySelector("#root").innerHTML = `
<div>
${entries}
</div>
`;
}
render();
https://jsfiddle.net/m3ws94zo/2/
The idea is to add a input to enter links separated by coma. In a real solution, you probably will need to validate the urls
I have a requirement where I have to suggest in the data list and when a user selects any of the datalist options, I have to update other input fields accordingly.
Here is my input field and Datalist code.
<input type="text" v-model="party.name" class="form-control form-control-sm shadow-sm" #input="searchPartyByName()" placeholder="Party name" list="queriedParties"/>
<datalist id="queriedParties">
<option v-for="party in queriedParties">{{party.name}}</option>
</datalist>
Now, what I want is, When a user hits enter or click on specific data list option, I want to update my this input field (Which is by default with data list) but I also want to set other form fields.
I have bound other form fields with my party data object. So, Only if I can update my party data object by any event on datalist option, I will be happy! I want something like this.
<option v-for="party in queriedParties" #click="setParty(party)">{{party.name}}</option>
I already tried the above-given example but it's not working. I also tried with #change but it's not working too!
Is there any way to accomplish this? I checked almost all the articles, jsfiddles and codepens available but none of them solves my issue.
datalist doesn't have events but the input does. You should do the following:
<template>
<input type="text" v-model="party.name" .... />
<datalist id="queriedParties">
<option v-for="party in queriedParties">{{party.name}}</option>
</datalist>
</template>
<script>
export default {
watch: {
party: {
deep: true,
handler (old_party, new_party) {
if (old_party.name !== new_party.name) this.searchPartyByName(new_party.name)
}
}
}
</script>
It seems that your queriedParties is an array of objects. Does it work if you have just an array of strings?
For objects use something along these lines:
<template>
<div class="sourceselection">
<div>
<div class="jumbotron">
<h2><span class="glyphicon glyphicon-list-alt"></span> News List</h2>
<h4>Select News Source</h4>
<input v-model="source" list="newssources-list" v-on:input="sourceChanged"
name="source-selection" id="source-selection" class="form-control"
placeholder="Please specify news source ..."/>
<datalist id="newssources-list">
<option v-for="source in sources" v-bind:value="source.name" v-bind:label="source.name"></option>
</datalist>
<div v-if="deepSource">
<h6>{{deepSource.description}}</h6>
<a v-bind:href="deepSource.url" class="btn btn-primary" target="_blank">Go To {{deepSource.name}} Website</a>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'sourceselection',
data () {
return {
sources: [],
source: '',
deepSource: ''
}
},
methods: {
sourceChanged: function(e) {
console.log("source = "+this.source+" new value = "+e.target.value);
var newSource = e.target.value;
// only action if value is different from current deepSource
if (newSource!= this.deepSource.name) {
for (var i=0; i<this.sources.length; i++) {
if (this.sources[i].name == newSource) {
this.deepSource = this.sources[i];
this.source = this.deepSource.name;
}
}
this.$emit('sourceChanged', this.deepSource.id);
}
}
},
created: function () {
var api = "https://newsapi.org/v1/sources?language=en";
this.axios.get(api).then((response) => {
this.sources = response.data.sources;
});
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
There is no event in datalist, so you can't handle, you'd better write your own list. Here is a example open in codepen:
//pug
#app
.form-group.has-feedback
input.input-search.form-control(type='text', v-model='word', placeholder='Search')
ul#list(v-if='Object.keys(filtered_projects).length > 0')
li(v-for='(value, key) in filtered_projects', #click='gotoProjectPage(key)')
span {{value}}
p {{key}}
span.glyphicon.glyphicon-search.form-control-feedback
/*css*/
body {
margin: 10px;
}
#app {
width: 400px;
}
#list {
font-size: 12px;
list-style: none;
margin: 0;
padding: 5px 0;
background-color: white;
border-radius: 0 0 5px 5px;
border: 1px #ccc solid;
}
#list li {
display: block;
padding: 5px 15px;
}
#list li:hover {
background-color: #ccc;
}
#list li span {
font-weight: 550;
}
#list li p {
margin: 5px 0 0;
}
//js
var app = new Vue({
el: '#app',
data: {
word: '',
projects: {"DataCenterMetro":"TEST1","IFF_Handway":"国际香料","SPH_Handway":"上药控股广东有限公司空调系统","QingTang_GZ":"广州地铁_清塘站","BTE_Handway":"白天鹅宾馆","NSSC_SZ":"深圳地铁_南山书城站","TA0301_Handway":"天安云谷二期"}
},
computed: {
filtered_projects: function () {
var vm = this, result = {};
if (vm.word) {
for(var key in vm.projects) {
if(key.toLowerCase().indexOf(vm.word) != -1 || vm.projects[key].toLowerCase().indexOf(vm.word) != -1)
result[key] = vm.projects[key];
}
}
return result;
}
},
created: function () {
var vm = this;
//TODO get projects
},
methods: {
gotoProjectPage: function (key) {
console.log('/map_login?project=' + key);
//TODO handle
}
},
});
I have a React app here that works in many browsers:
<!DOCTYPE html>
<html>
<head>
<title>React! React! React!</title>
<script src="https://unpkg.com/react#15.3.2/dist/react.js"></script>
<script src="https://unpkg.com/react-dom#15.3.2/dist/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
<style>
body {
padding: 50px;
background-color: #66CCFF;
font-family: sans-serif;
}
.todoListMain .header input {
padding: 10px;
font-size: 16px;
border: 2px solid #FFF;
}
.todoListMain .header button {
padding: 10px;
font-size: 16px;
margin: 10px;
background-color: #0066FF;
color: #FFF;
border: 2px solid #0066FF;
}
.todoListMain .header button:hover {
background-color: #003399;
border: 2px solid #003399;
cursor: pointer;
}
.todoListMain .theList {
list-style: none;
padding-left: 0;
width: 255px;
}
.todoListMain .theList li {
color: #333;
background-color: rgba(255,255,255,.5);
padding: 15px;
margin-bottom: 15px;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="container">
</div>
<script type="text/babel">
var destination = document.querySelector("#container");
// es6 is working in the browser :)
let y = [1, 3, 6, 15, 39, 88].find(x => x > 39 && x < 90)
var TodoItems = React.createClass({
render: function(){
var todoEntries = this.props.entries;
function createTask(item){
return (
<li key={item.key}>
<span>{item.text}</span>
<a href="" data-id="{item.id}"
className="remove-filter"
onClick={this.props.remove.bind(item)}
>
remove
</a>
</li>
)
}
// var listItems = todoEntries.map(createTask.bind(this));
return (
<ul className="theList">
{this.props.entries.map(createTask.bind(this))}
</ul>
);
}
});
var TodoList = React.createClass({
getInitialState: function(){
return {
items: []
};
},
addItem: function(e) {
var itemArray = this.state.items;
itemArray.push(
{
text: this._inputElement.value,
key: this.state.items.length
}
);
this.setState({
items: itemArray
})
this._inputElement.value = "";
e.preventDefault();
},
// removing items from a list
// https://stackoverflow.com/questions/27817241/how-to-remove-an-item-from-a-list-with-a-click-event-in-reactjs
removeItem: function(item, event){
event.preventDefault();
var items = this.state.items.filter(function(itm){
return item.id !== itm.id;
});
this.setState({ items: items });
},
render: function() {
return (
<div className="todoListMain">
<div className="header">
<form onSubmit={this.addItem}>
<input ref={(a) => this._inputElement = a}
placeholder="enter task" />
<button type="submit">add</button>
</form>
</div>
<TodoItems remove={this.removeItem} entries={this.state.items} />
</div>
);
}
});
ReactDOM.render(
<div>
<TodoList/>
</div>,
destination
);
</script>
</body>
</html>
I have followed how to remove an item from a list with a click event in ReactJS? and it seems to be working, with a few issues.
First, the example references <a href data-..., but this did not work and redirected me to file:///Users/cchilders/tutorials/javascript/react/todo-list/true, where it got true from something it evaluated (true should be the index.html)
Deletion works using href="", but it flashes the page in an ugly manner, and the usual suspects to make an href do nothing don't work...
...if I try href="#" or href="javascript:;" and similar I get
embedded:60 Uncaught TypeError: Cannot read property 'preventDefault' of undefined
Second, I am getting warning
react.js:20478 Warning: bind(): React component methods may only be bound to the component instance. See TodoList
no matter what, for each thing I try.
Third, it is deleting all items in the list on remove, not just 1 item.
How can I make React do this deletion onclick without refreshing the page, and delete 1 item at a time?
There are few things that u need to change, check the jsfiddle for working example, do the changes in ur code accordingly.
*Don't write like this: {this.props.entries.map(createTask.bind(this))}
instead of that just call a method {this.createTask()} from render, that function will return the complete list, n define createTask outside of the render method. like this:
createTask: function(){
return this.props.entries.map(item=>{
return (
<li key={item.key}>
<span>{item.text}</span>
<a href="#" data-id="{item.id}"
className="remove-filter"
onClick={()=>this.props.remove(item)}
>
remove
</a>
</li>
)})
},
*U forgot to give the dead link to href, don't leave it empty define it like this: href="#".
*Don't bind the props remove method with onClick, use it like normal method calling, like this: onClick={()=>this.props.remove(item)}.
Check jsfiddle: https://jsfiddle.net/79eax14s/
Let me know if u need any help in this.
Title pretty much explains it all. Inputting ngSwipeLeft="someFunction()" does not seem to work as I hoped it would. Maybe I am doing it wrong, but what are your ideas? Here is the documentation for ngSwipeLeft.
Example
Thanks,
Ben
I think what you need to do is create a controller for that javascript, and then work off of its scope.
<div ng-show="!showActions" data-ng-swipe-left="someFunction()">
Some list content, like an email in the inbox
</div>
<div ng-show="showActions" data-ng-swipe-right="someFunction()">">
<button ng-click="reply()">Reply</button>
<button ng-click="delete()">Delete</button>
</div>
And the JS
$scope.showActions = false;
$scope.someFunction = function () {
$scope.showActions = !$scope.showActions;
};
That is how I do it in my applications. I hope it helps.
Here is the Plunk.
The plunk works but it is a little off. It sometimes highlights instead of switching over. It works best when swiping to the right side.
<div ng-controller="MyCtrl">
<div>
<div>
<pre> Left swipes: {{model.left}}</pre>
</div>
<div>
<pre>Right swipes: {{model.right}}</pre>
</div>
<div>
<pre>Touch clicks: {{model.click}} </pre>
</div>
</div>
<div class="swipy"
ng-swipe-left="swipeLeft()"
ng-swipe-right="swipeRight()"
ng-click="touchClick()">
Swipe me !
</div>
</div>
<style type="text/css">
div {
font-size: 0.9em;
}
div.swipy {
text-align: center;
padding: 15px;
margin: 5px;
border-radius: 2px;
border: 3px groove gray;
background-color: light-gray;
}
</style>
<script type="text/javascript">
app.controller('MyCtrl', function ($scope) {
$scope.model = {
left: 0,
right: 0,
click: 0
};
$scope.swipeLeft = function () {
$scope.model.left += 1;
};
$scope.swipeRight = function () {
$scope.model.right += 1;
};
$scope.touchClick = function () {
$scope.model.click += 1;
};
});
</script>