Vuetify treeview search behavior - search

Hello and Happy new Year guys,
Again I ask about v-treeview search. When I do my filter, the behavior do not satisfy me.
I updated my version of vuetify to 1.4.0. And I'm using vue 2.5.15
https://codepen.io/anon/pen/PXeMmy?&editors=101
HTML
<div id="app">
<v-container grid-list-md>
<v-layout wrap>
<v-flex xs6>
<!-- Search Field -->
<v-text-field label="search" v-model="search" box>
</v-text-field>
<!-- Treeview -->
<v-treeview :items="filteredTree"
v-model="selected"
active-class="grey lighten-4 indigo--text"
item-key="name"
selected-color="blue"
selectable
hoverable>
</v-treeview>
</v-flex>
<v-flex xs6>
<v-chip v-for="(s , i) in selected" :key="i">
{{s}}
</v-chip>
</v-flex>
</v-layout>
</v-container>
</div>
JS :
new Vue({
el: '#app',
data(){
return{
search: '',
tree: [
{
id: 1,
name: 'Applications',
children: [
{ id: 2, name: 'Calendar' },
{ id: 3, name: 'Chrome' },
{ id: 4, name: 'Webstorm' }
]
},
{
id: 5,
name: 'Languages',
children: [
{ id: 6, name: 'English' },
{ id: 7, name: 'French' },
{ id: 8, name: 'Spannish' }
]
}
],
selected: []
}
},
computed:{
filteredTree: {
get: function() {
let regexp = new RegExp(this.search, "i")
return this.filterTree(this.tree, regexp) || []
},
},
},
methods: {
filterTree: function(tree, filter) {
if (!Array.isArray(tree)) return null
return JSON.parse(JSON.stringify(tree)).filter(function matchName(o) {
let temp;
if (o.name.match(filter)) {
return true;
}
if (!Array.isArray(o.children)) {
return false;
}
temp = o.children.filter(matchName);
if (temp.length) {
o.children = temp;
return true;
}
});
}
}
})
In this exemple when I search "Calen", only "Application -> Calendar" is visible. Until now, it's what I want.
But when I select Calendar, "Application" is also selected; and when I clear the filter, all the children of "Application" are selected too. And I'd like to select "Calendar" and when I clear I don't want its siblings to be selected.
Thank you for reading

Related

Content in tab does not show in Shopware 6

I have added a custom tab on my module’s details page, however, the tab is rendered but the content for the tab isn’t showing. There isn’t any error in the console log as well.
index.js
import './page/wt-shopfinder-list';
import './page/wt-shopfinder-detail';
import './view/wt-shopfinder-detail-base';
import './view/wt-shopfinder-detail-review';
const { Module } = Shopware;
Module.register('example-shopfinder', {
type: 'plugin',
name: 'ExampleShopFinder',
title: 'example-shopfinder.general.mainMenuItemGeneral',
description: 'example-shopfinder.general.descriptionTextModule',
version: '1.0.0',
targetVersion: '1.0.0',
color: '#9AA8B5',
icon: 'default-shopping-paper-bag',
entity:'wt_shop_finder',
routes: {
index: {
components: {
default: "wt-shopfinder-list"
},
path: 'index',
},
detail: {
component: 'wt-shopfinder-detail',
path: 'detail/:id',
redirect: {
name: 'example.shopfinder.detail.base',
},
children: {
base: {
component: 'wt-shopfinder-detail-base',
path: 'base',
meta: {
parentPath: 'example.shopfinder.index'
},
},
review: {
component: 'wt-shopfinder-detail-review',
path: 'review',
meta: {
parentPath: 'example.shopfinder.index'
},
},
},
meta: {
appSystem: {
view: 'detail',
},
},
props: {
default(route) {
return {
shopFinderId: route.params.id,
};
},
},
}
},
navigation: [{
id: 'wt-shopfinder',
label: 'example-shopfinder.menu.mainMenuItemGeneral',
color: '#ff3d58',
icon: 'default-shopping-paper-bag-product',
path: 'example.shopfinder.index',
parent: "sw-marketing",
position: 100,
}],
});
wt-shopfinder-detail/wt-shopfinder-detail-html.twig
<sw-tabs
class="wt_shopfinder-detail-page__tabs"
position-identifier="wt-shopfinder-detail"
>
{% block wt_shopfinder_detail_content_tabs_general %}
<sw-tabs-item
:route="generalRoute"
:title="$tc('sw-customer.detail.tabGeneral')"
:disabled="false"
>
{{ $tc('sw-promotion-v2.detail.tabs.tabGeneral') }}
</sw-tabs-item>
{% endblock %}
{% block wt_shopfinder_detail_content_tabs_general2 %}
<sw-tabs-item
:route="reviewRoute"
:title="$tc('sw-customer.detail.tabGeneral')"
:disabled="false"
>
Review
</sw-tabs-item>
{% endblock %}
</sw-tabs>
wt-shopfinder-detail/index.js
//Sharing only the url part for tab navigation
generalRoute() {
console.log("ID = "+this.shopFinderId);
return {
name: 'webbytroops.shopfinder.detail.base',
params: { id: this.shopFinderId },
};
},
wt-shopfinder-detail-base/index.js
import template from './wt-shopfinder-detail-base.html.twig';
const { Component } = Shopware;
const { Criteria } = Shopware.Data;
Component.register('wt-shopfinder-detail-base', {
template,
inject: ['repositoryFactory'],
metaInfo() {
return {
title: "Custom"
};
}
});
wt-shopfinder-detail-base/wt-shopfinder-detail-base.html.twig
<sw-card title="Custom">
Hello world!
</sw-card>
The correct pattern for the route would be {moduleName}.{routeName}.{childName} and in the module name dashes are replaced by dots. So the correct route in your case should be example.shopfinder.detail.base.
Also, unless you omitted it, you're missing the router-view tag after the sw-tabs component.
<sw-container>
<sw-tabs>
...
</sw-tabs>
<router-view />
</sw-container>

Algolia autocomplete: How do I highlight items?

I use Algolia autocomplete in "standalone" mode, meaning without the commercial Algolia service to return the search results; I have my own server respond with an array of search results.
How do I highlight matches in my returned items/strings (search results)?
The backend must return results that are already highlighted using a tag such as: <mark>this-is-to-be-highlighted</mark>. Here's an example result array for an search for "pie":
const items = [
{ some_attribute: 'Apple <mark>pie</mark>' },
{ some_attribute: 'American <mark>pie</mark>' },
{ some_attribute: 'Chocolate <mark>pie</mark>' }
]
The complete javascript code would then be something like this:
import { autocomplete } from "#algolia/autocomplete-js"
autocomplete({
container: '#search_input',
// ...
getSources({ query }) {
// This would be an example response from your server
const items = [
{ some_attribute: 'Apple <mark>pie</mark>' },
{ some_attribute: 'American <mark>pie</mark>' },
{ some_attribute: 'Chocolate <mark>pie</mark>' }
]
return [
{
sourceId: 'pies',
getItems({ query }) {
const HIGHLIGHT_PRE_TAG = '__aa-highlight__'
const HIGHLIGHT_POST_TAG = '__/aa-highlight__'
return items.map((item) => ({
item,
_highlightResult: {
some_attribute: {
value: item.some_attribute
.replace(/<mark>/g, HIGHLIGHT_PRE_TAG)
.replace(/<\/mark>/g, HIGHLIGHT_POST_TAG)
}
}
}))
},
templates: {
// ...
item({ item, components, html }) {
return html`<div className="aa-ItemWrapper">
<div className="aa-ItemContent">
<div className="aa-ItemContentBody">
<div className="aa-ItemContentTitle">
${components.Highlight({ hit: item, attribute: 'some_attribute' })}
</div>
</div>
</div>
</div>`
},
// ...
}
},
// ...
]
},
// ...
})

Vuetify Combobox add new item as object instead of string

I am building a new/edit item form using Vuetify(v2.6.3). My form has multiple combobox's that pull their items from a backend API as objects. I would like to be able to add new items, which the combobox is able to do. However, when I add a new item it's added as a string. Is there a way to add that new item as an object instead?
I only need the new object to have a name key in order to send it to the API to be created
Desired New item from v-combobox:
{
name: 'New Item',
}
Simplified list of items returned from API and available as combobox choices:
[
{
id: 1,
name: 'Item 1',
createdAt: '2020-01-01',
updatedAt: '2020-01-01'
},
{
id: 2,
name: 'Item 2',
createdAt: '2020-01-01',
updatedAt: '2020-01-01'
},
{
id: 3,
name: 'Item 3',
createdAt: '2020-01-01',
updatedAt: '2020-01-01'
}
]
Here is a simplified version of my Form:
<template>
<v-card>
<v-card-title>
<span class="text-h5">Edit Item</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col>
<v-combobox
v-model="item"
:items="items"
item-text="name"
item-value="id"
label="ComboBox"
return-object
></v-combobox>
</v-col>
</v-row>
</v-container>
</v-card-text>
</v-card>
</template>
<script>
export default {
name: 'TestForm',
data() {
return {
item: null,
items: [
{
id: 1,
name: 'Item 1',
createdAt: '2020-01-01',
updatedAt: '2020-01-01',
},
{
id: 2,
name: 'Item 2',
createdAt: '2020-01-01',
updatedAt: '2020-01-01',
},
{
id: 3,
name: 'Item 3',
createdAt: '2020-01-01',
updatedAt: '2020-01-01',
},
],
}
},
}
</script>
In my method which sends the form to the API, I could check the value of each combobox and convert to an object if needed, but I am wondering if it's possible to handle it in the combobox component.
VComboBox doesn't seem to support that, but you could workaround it by using the component's change-event to add a new object with the entry if needed:
Add a change-event handler (e.g., named onChange) on the v-combobox.
In onChange(), lookup the entry in items by name (i.e., corresponding to the VComboBox's item-text prop).
If found, set item to the existing item.
Otherwise, create a new object with that entry, and set item to the newly created object. Note the new object's id (i.e., corresponding to VComboBox's item-value prop) must be unique for VComboBox to create and track it.
<v-combobox
v-model="item"
#change="onChange" 1️⃣
/>
let nextId = 1
export default {
⋮
methods: {
addItem(name) {
const newItem = {
id: nextId++,
name,
}
this.items.push(newItem)
return newItem
},
1️⃣
onChange(entry) {
if (typeof entry === 'string' && entry.trim()) {
2️⃣
const item = this.items.find(item => item.name === entry)
if (item) {
3️⃣
this.item = item
} else {
4️⃣
this.item = this.addItem(entry)
}
}
},
},
}
demo
I found the accepted answer useful but here is a similar solution that allows for a multiple selection combo box using chips. I used this to implement a way for a user to select multiple "Tags":
Ex. Stackblitz runnable example
<v-combobox
v-model="selectedItems"
:items="items"
chips
clearable
multiple
#change="OnChange"
item-text="TagName"
item-value="TagId"
label="Categories"
solo
prepend-icon="mdi-tag-multiple"
return-object>
<template v-slot:selection="{ attrs, item, select, selected }">
<v-chip
v-bind="attrs"
:input-value="selected"
color="primary"
close
#click="select"
#click:close="RemoveTag(item)"
>
<span>{{ item.TagName }}</span>
</v-chip>
</template>
</v-combobox>
Here is the code that handles the Add/Removal of these tags:
private OnChange(tags: any) {
let tagsArray = tags as [];
tagsArray.forEach(function(tag: any) {
// New tags are added as type "string" so we need to convert this to a Tag
// Iterate through the selected Tags and for each "string" found convert it to a Tag
if (typeof tag === 'string' && tag.trim()) {
const item = this.selectedItems.find(item => item === tag);
if (item) {
let newTag = new Tag(0, tag);
// Remove the string based tag
const index = this.selectedItems.indexOf(tag, 0);
if (index > -1) {
this.selectedItems.splice(index, 1);
}
// Add a new tag object instead
this.selectedItems.push(newTag);
return;
}
}
}.bind(this))
}
private RemoveTag(tagToRemove: Tag) {
var indexOfItemToRemove = this.selectedItems.findIndex(x => x.TagName == tagToRemove.TagName);
this.selectedItems.splice(indexOfItemToRemove, 1);
}
It does not appear that a ComboBox can directly return an object when adding a new item. However it looks like you can leverage the input event of the component to run a method that converts to an object.
Here is how I call the method on the component's input event:
<v-combobox
v-model="item"
:items="items"
item-text="name"
item-value="id"
label="ComboBox"
return-object
#input="makeObject"
></v-combobox>
#input="makeObject" listens for the component's input event and calls the makeObject method and passes the currently selected item
Then I was able to write a method which checks if the combobox value is a string. If so then it converts it to an object
<script>
export default {
name: "TestForm",
data() {
return {
item: null
// Remaining code omitted for readability
}
}
methods: {
makeObject(val) {
if (typeof val === "string") {
this.item = {
name: val,
};
}
},
},
};
</script>
Here is my full component:
<template>
<v-card>
<v-card-title>
<span class="text-h5">Edit Item</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col>
<v-combobox
v-model="item"
:items="items"
item-text="name"
item-value="id"
label="ComboBox"
return-object
#input="makeObject"
></v-combobox>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-text>
{{ item }}
</v-card-text>
</v-card>
</template>
<script>
export default {
name: "TestForm",
data() {
return {
item: null,
items: [
{
id: 1,
name: "Item 1",
createdAt: "2020-01-01",
updatedAt: "2020-01-01",
},
{
id: 2,
name: "Item 2",
createdAt: "2020-01-01",
updatedAt: "2020-01-01",
},
{
id: 3,
name: "Item 3",
createdAt: "2020-01-01",
updatedAt: "2020-01-01",
},
],
};
},
methods: {
makeObject(val) {
if (typeof val === "string") {
this.item = {
name: val,
};
}
},
},
};
</script>
sandbox link

How do I create a multi-select header filter in tabulator?

This question has been asked several times in various forms over the years in the Tabulator GitHub repository. Here are a few instances:
https://github.com/olifolkerd/tabulator/issues/527, https://github.com/olifolkerd/tabulator/issues/1759
I'm looking for an example of how to achieve this using a dropdown menu of some form --- ideally as described in #1759 (dropdown with checkboxes) but another solution that would work for us is a "select" editor that adds/removes CSVs in the header filter when a value is selected/deselected (extending on the example provided in #527).
Hopefully someone with experience working with custom header filters / editors in tabulator can provide an example of a multi-select header filter dropdown, but if not, then I will post a JSFiddle link myself once I've got something that works.
Checkout: https://github.com/olifolkerd/tabulator/issues/527#issuecomment-850900451
Simple Answer by AkshayaBrianTauro
{
field: "book_name",
title: "Book Name",
headerFilterPlaceholder: " ",
headerFilter: 'select',
headerFilterFunc:"in",
headerFilterParams: {values:true, sortValuesList:"asc", multiselect:true}
},
Here is an example of a custom header filter for tabulator of 'select multiple' type. It can be converted to a dropdown style if desired using external sources such as Chosen or multiselect.js
(I recommend running the below Code Snippet in Full Page view).
const speciesTypes = ['Human', 'Android', 'Betazoid', 'Klingon', 'Ferengi', 'Tamarian'];
function multiSelectHeaderFilter(cell) {
var values = speciesTypes;
const filterFunc = (rowData) => {
return values.includes(rowData['species']);
}
const getSelectedValues = (multiSelect) => {
var result = [];
var options = multiSelect && multiSelect.options;
var opt;
for (var i = 0, iLen = options.length; i < iLen; i++) {
opt = options[i];
if (opt.selected) {
result.push(opt.value || opt.text);
}
}
return result;
}
const onChange = () => {
var editor = document.getElementById('speciesSelector');
values = getSelectedValues(editor);
console.log("values: " + values);
cell.getColumn().getTable().removeFilter(filterFunc);
cell.getColumn().getTable().addFilter(filterFunc);
}
var select = document.createElement("select");
select.multiple = "multiple";
select.id = 'speciesSelector';
select.class = "chosen-select";
select.style = 'width: 100%';
speciesTypes.forEach(species => {
select.innerHTML += "<option id='" + species + "' value='" + species + "' selected='selected'>" + species + "</option>";
});
cell.getColumn().getTable().addFilter(filterFunc);
select.addEventListener('change', onChange);
return select;
}
var table = new Tabulator("#tabulator", {
layout: "fitColumns",
data: [{
name: 'Geordi La Forge',
species: 'Human'
}, {
name: 'Dathon',
species: 'Tamarian'
}, {
name: 'Jean-Luc Picard',
species: 'Human'
}, {
name: 'Worf, son of Mogh',
species: 'Klingon'
}, {
name: 'Tasha Yarr',
species: 'Human'
}, {
name: 'Data',
species: 'Android'
}, {
name: 'Wesley Crusher',
species: 'Human'
}, {
name: 'Jalad',
species: 'Tamarian'
}, {
name: 'Lwaxana Troi',
species: 'Betazoid'
}, {
name: 'Temba',
species: 'Tamarian'
}, {
name: 'T\'Kuvma',
species: 'Klingon'
}, {
name: 'Lore',
species: 'Android'
}, {
name: 'Noonian Soongh',
species: 'Human'
}, {
name: 'Darmok',
species: 'Tamarian'
}, {
name: 'Reittan Grax',
species: 'Betazoid'
}, {
name: 'Quark',
species: 'Ferengi'
}],
headerSort: true,
columns: [{
title: 'Name',
field: 'name',
sorter: 'string'
}, {
title: 'Species',
field: 'species',
sorter: 'string',
headerFilter: multiSelectHeaderFilter,
headerFilterLiveFilter: false
}, ],
});
<html>
<head>
<link href="https://unpkg.com/tabulator-tables#4.5.3/dist/css/tabulator.min.css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/tabulator-tables#4.5.3/dist/js/tabulator.min.js"></script>
</head>
<body>
<div id="tabulator"></div>
</body>
</html>
JSFiddle: https://jsfiddle.net/jjech/3th28pv0/
See my answer to Tabulator Multiple Filter in the same Column (show dropbox)
Extend as you see fit...
I dont think <select> support checkboxes as <option>'s, but it would be trivial to replace the <select> with a different style of "pulldown" that does.

Extracting properties from material-ui's GridList

I only started studying React a few days ago so please forgive me if this question sounds really stupid.
In this work assignment, I have to implement a 'Like' system using material-ui's GridList. There will be eight pictures in total where users can like them by clicking on the like button. In my current code, users can click on the like button but all the like buttons will be affected instead of just one. Furthermore, the number of likes does not increase.
So my question is, how can I change the number of likes when a user clicks the 'Like' button and make sure only 1 button is affected? I have tried props and even lodash but I just cannot seem to figure out the problem. Below is my entire code for the GridList portion. Any help would be greatly appreciated.
import _ from 'lodash';
import React from 'react';
import {GridList, GridTile} from 'material-ui/GridList';
import Subheader from 'material-ui/Subheader';
import baseTheme from 'material-ui/styles/baseThemes/lightBaseTheme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
//GridList style
const styles = {
root: {
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-around',
},
gridList: {
width: 1000,
height: 500,
},
};
//data for the GridList
var tilesData = [
{
img: './images/image_01.jpg',
title: 'Breakfast',
likes: 0,
},
{
img: './images/image_02.jpg',
title: 'Tasty burger',
likes: 0,
},
{
img: './images/image_03.jpg',
title: 'Camera',
likes: 0,
},
{
img: './images/image_04.jpg',
title: 'Morning',
likes: 0,
},
{
img: './images/image_05.jpg',
title: 'Hats',
likes: 0,
},
{
img: './images/image_06.jpg',
title: 'Honey',
likes: 0,
},
{
img: './images/image_07.jpg',
title: 'Vegetables',
likes: 0,
},
{
img: './images/image_08.jpg',
title: 'Water plant',
likes: 0,
},
];
export default class Grid extends React.Component {
constructor(props){
super(props);
this.state = {
like: false,
likes: tilesData.likes,
};
this.post = this.post.bind(this);
this.delete = this.delete.bind(this);
}
//if Like button is clicked
post(){
this.setState({ like: true});
let likes = this.state.likes;
likes++;
this.setState({likes: likes});
//this.tilesData.likes = likes;
}
//if Like button is "unclicked"
delete(){
this.setState({ like: false});
let likes = this.state.likes;
likes--;
this.setState({likes: likes});
//this.tilesData.likes = likes;
}
getChildContext() {
return { muiTheme: getMuiTheme(baseTheme) };
}
render(){
const likeBtn = this.state.like ? <img src="./images/icons/icon_2.png" onClick={this.delete} /> : <img src="./images/icons/icon_1.png" onClick={this.post} />;
return (
<div style={styles.root}>
<GridList
cellHeight={200}
cols={4}
style={styles.gridList}
>
<Subheader>December</Subheader>
{tilesData.map((tile) => (
<GridTile
key={tile.img}
title={tile.title}
subtitle={<span>Likes: <b>{tile.likes}</b></span>}
actionIcon={likeBtn}
>
<img src={tile.img} />
</GridTile>
))}
</GridList>
</div>
);
}
}
Grid.childContextTypes = {
muiTheme: React.PropTypes.object.isRequired,
}
Problem
'State' of like button is defined outside the loop means same 'state' is shared with all GridTile components(for all images).
When you clicked on 'like' button then you are changing the 'state' of 'like' button in parent component that is Grid and same 'state' is used for all like buttons.
That's why it is impacting all like buttons.
Solution
'state' should be defined separately for each like button. Also delete and post method should be defined inside loop means in GridTile.
But GridTile is part of material-ui library so instead of changing this library create a wrapper on GridTile component.
Grid component will call component lets say it GridTileCustom component inside loop.
Inside GridTileCustom component you need to define delete and post method which you are using in 'onClick' event
So your final code will look like
import React from 'react';
import {GridList, GridTile} from 'material-ui/GridList';
import Subheader from 'material-ui/Subheader';
import baseTheme from 'material-ui/styles/baseThemes/lightBaseTheme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import IconButton from 'material-ui/IconButton';
const thumbsIcon = "glyphicon glyphicon-thumbs-up";
const styles = {
root: {
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-around',
},
gridList: {
width: 1000,
height: 500,
},
};
var tilesData = [
{
img: './images/image_01.jpg',
title: 'Breakfast',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_02.jpg',
title: 'Tasty burger',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_03.jpg',
title: 'Camera',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_04.jpg',
title: 'Morning',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_05.jpg',
title: 'Hats',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_06.jpg',
title: 'Honey',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_07.jpg',
title: 'Vegetables',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_08.jpg',
title: 'Water plant',
likes: 0,
icon: './images/icons/icon_1.png',
},
];
export default class Grid extends React.Component {
constructor(props){
super(props);
this.state = {
like: false,
likes: tilesData.likes,
};
// this.post = this.post.bind(this);
// this.delete = this.delete.bind(this);
}
// post(){
// this.setState({ like: true});
// let likes = this.state.likes;
// likes++;
// this.setState({likes: likes});
// //this.tilesData.likes = likes;
// }
// delete(){
// this.setState({ like: false});
// let likes = this.state.likes;
// likes--;
// this.setState({likes: likes});
// //this.tilesData.likes = likes;
// }
getChildContext() {
return { muiTheme: getMuiTheme(baseTheme) };
}
render(){
return (
<div style={styles.root}>
<GridList
cellHeight={200}
cols={4}
style={styles.gridList}
>
<Subheader>December</Subheader>
{tilesData.map((tile) => (
<GridTileInternal
key={tile.img}
img={tile.img}
title={tile.title}
subtitle={tile.likes}
// actionIcon={likeBtn}
>
</GridTileInternal>
))}
</GridList>
</div>
);
}
}
class GridTileInternal extends React.Component {
constructor(props){
super(props);
this.state = {
like: false,
likes: tilesData.likes,
};
this.post = this.post.bind(this);
this.delete = this.delete.bind(this);
}
post(){
this.setState({ like: true});
let likes = this.state.likes;
likes++;
this.setState({likes: likes});
//this.tilesData.likes = likes;
}
delete(){
this.setState({ like: false});
let likes = this.state.likes;
likes--;
this.setState({likes: likes});
//this.tilesData.likes = likes;
}
render(){
const likeBtn = this.state.like ? <img src="./images/icons/icon_2.png" onClick={this.delete} /> : <img src="./images/icons/icon_1.png" onClick={this.post} />;
return (
<GridTile
key={this.props.img}
title={this.props.title}
subtitle={<span>Likes: <b>{this.props.subtitle}</b></span>}
actionIcon={likeBtn}
>
<img src={this.props.img} />
</GridTile>
);
}
}
Grid.childContextTypes = {
muiTheme: React.PropTypes.object.isRequired,
}

Resources