Share data from one component with another component in same App.js - vue.js

I have the following App.js file that runs on WebSphere. I just added a new component that needs a value from the same API the larger component uses. I don't want to hit the API twice. I'm thinking I need to move the data access into the new Vue({… and then pass the result into the two components. How do I do that? Can someone point me to sample code?
Vue.component('greeting-portlet-text', {
data: function() {
return {
today: '',
bonusPageLink: '/wps/myportal/k/payroll/bonus'
};
},
methods: {
getFormattedTodaysDate: function() {
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1; //January is 0!
var yyyy = today.getFullYear();
today = mm + '/' + dd + '/' + yyyy;
return today;
}
},
mounted: function() {
this.today = this.getFormattedTodaysDate();
},
template:
'<div class="greeting-text"><h1>Welcome ' +
_greentin_app_config.user.firstName +
'</h1>' +
' <p class="subtitle">Your bonus progress as of {{ today }}</p> ' +
' <div class="greeting-buttons greeting-buttons-top show-for-large">' +
' <greeting-portlet-buttons></greeting-portlet-buttons>' +
' <a :href="bonusPageLink" class="button expanded mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent highlight">View Full Bonus Progress</a>' +
' </div>' +
'</div>'
});
Vue.component('greeting-portlet-buttons-panel', {
data: function() {
return {
bonusPageLink: '/wps/myportal/k/payroll/bonus'
};
},
template:
'<div class="greeting-buttons greeting-buttons-bottom grid-x grid-margin-x">' +
' <div class="cell small-12 medium-6">' +
' <greeting-portlet-buttons></greeting-portlet-buttons>' +
' </div>' +
' <div class="cell small-12 medium-6"><a :href="bonusPageLink" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent highlight">View Full Bonus Progress</a></div>' +
'</div>'
});
Vue.component('greeting-portlet-buttons', {
data: function() {
return {
SmartDriveLink: '/wps/myportal/k/company-info/news/smartdrivefaq'
};
},
template:
'<div>' +
' <a v-if="SmartDriveScore>=25 && SmartDriveScore!=99999" :href="SmartDriveLink" class="button expanded mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-color--red-A700 mdl-color-text--white">SmartDrive Score: {{SmartDriveScore}} <i class="material-icons">thumb_down_alt</i></a>' +
' <a v-if="SmartDriveScore=== 99999" :href="SmartDriveLink" class="button expanded mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-color--yellow">SmartDrive Score: <i class="material-icons">phone_in_talk</i> CALL DDM</a>' +
' <a v-if="SmartDriveScore<25" :href="SmartDriveLink" class="button expanded mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-color--green mdl-color-text--white">SmartDrive Score: {{SmartDriveScore}} <i class="material-icons">thumb_up_alt</i></a>' +
'</div>'
});
Vue.component('greeting-portlet-progress', {
data: function() {
return {
bonus: {
payBand: {
showPayBand: false // default
},
milageTiers: {
tier1: 0,
tier2: 0,
tier3: 0,
tier4: 0
},
rateTiers: {
tier1: 0,
tier2: 0,
tier3: 0,
tier4: 0
},
currentMileage: 872
},
viewStatus: {
dataLoaded: false
},
storageKey: 'bonusProgressData'
};
},
computed: {
tier1Miles: function() {
return this.formatNumber(this.bonus.milageTiers.tier1);
},
tier2Miles: function() {
return this.formatNumber(this.bonus.milageTiers.tier2);
},
tier3Miles: function() {
return this.formatNumber(this.bonus.milageTiers.tier3);
},
tier4Miles: function() {
return this.formatNumber(this.bonus.milageTiers.tier4);
},
tier1Rate: function() {
return '$' + this.bonus.rateTiers.tier1;
},
tier2Rate: function() {
return '$' + this.bonus.rateTiers.tier2;
},
tier3Rate: function() {
return '$' + this.bonus.rateTiers.tier3;
},
tier4Rate: function() {
return '$' + this.bonus.rateTiers.tier4;
},
tier1Percentage: function() {
return (
Math.floor(
(this.bonus.milageTiers.tier1 / this.bonus.milageTiers.tier4) * 100
) + '%'
);
},
tier2Percentage: function() {
return (
Math.floor(
(this.bonus.milageTiers.tier2 / this.bonus.milageTiers.tier4) * 100
) + '%'
);
},
tier3Percentage: function() {
return (
Math.floor(
(this.bonus.milageTiers.tier3 / this.bonus.milageTiers.tier4) * 100
) + '%'
);
},
tier4Percentage: function() {
return (
Math.floor(
(this.bonus.milageTiers.tier4 / this.bonus.milageTiers.tier4) * 100
) + '%'
);
},
currentMilage: function() {
return this.formatNumber(this.bonus.currentMileage);
},
progress: function() {
return this.progressNumber + '%';
},
progressNumber: function() {
var percentage = 0;
if (
this.bonus.currentMileage !== 0 ||
this.bonus.milageTiers.tier4 !== 0
) {
percentage = Math.floor(
(this.bonus.currentMileage / this.bonus.milageTiers.tier4) * 100
);
}
return percentage;
},
showPayBand: function() {
return this.bonus.payBand.showPayBand;
},
payBandMiles: function() {
return this.formatNumber(this.bonus.payBand.miles);
}
},
methods: {
loadBonusDataFromService: function() {
var app = this;
var servicePath =
_greentin_app_config.serviceBasePath +
'/v1/knight/portal/bonus/progress';
axios
.get(servicePath)
.then(function(response) {
app.bonus = response.data;
app.viewStatus.dataLoaded = true;
if (typeof storageWrap !== 'undefined') {
// cache the data
storageWrap.setItem(app.storageKey, app.bonus);
}
})
.catch(function(error) {
console.error(error);
});
},
getBonusData: function() {
var cachedData;
if (typeof storageWrap !== 'undefined') {
cachedData = storageWrap.getItem(this.storageKey);
}
// return cachedData if found otherwise load the data from service
if (cachedData) {
this.bonus = cachedData;
this.viewStatus.dataLoaded = true;
} else {
this.loadBonusDataFromService();
}
},
formatNumber: function(value) {
if (typeof value !== 'number') {
return value;
}
var formatter = new Intl.NumberFormat('en-US', {
style: 'decimal',
minimumFractionDigits: 0
});
return formatter.format(value);
}
},
mounted: function() {
this.getBonusData();
},
template:
'<div>' +
'<div v-if="viewStatus.dataLoaded" class="progress-wrapper">' +
'<div class="progress">' +
'<div class="progress-bar" v-bind:style="{ width: progress }">' +
'<span class="progress-bar__label" v-if="progressNumber > 9" >{{ currentMilage }} mi.</span>' +
'</div>' +
'<div class="progress-bar__marker" v-bind:style="{ left: tier1Percentage }">' +
'<span class="progress-bar__markerText">' +
'<span class="progress-bar__markerText__label">{{tier1Miles}}</span><br>' +
'<span class="progress-bar__markerText__value">{{tier1Rate}}</span>' +
'</span>' +
'</div>' +
'<div class="progress-bar__marker" v-bind:style="{ left: tier2Percentage }">' +
'<span class="progress-bar__markerText">' +
'<span class="progress-bar__markerText__label">{{tier2Miles}}</span><br>' +
'<span class="progress-bar__markerText__value">{{tier2Rate}}</span>' +
'</span>' +
'</div>' +
'<div class="progress-bar__marker" v-bind:style="{ left: tier3Percentage }">' +
'<span class="progress-bar__markerText">' +
'<span class="progress-bar__markerText__label">{{tier3Miles}}</span><br>' +
'<span class="progress-bar__markerText__value">{{tier3Rate}}</span>' +
'</span>' +
'</div>' +
'<div class="progress-bar__marker" v-bind:style="{ left: tier4Percentage }">' +
'<span class="progress-bar__markerText">' +
'<span class="progress-bar__markerText__label">{{tier4Miles}}+</span><br>' +
'<span class="progress-bar__markerText__value">{{tier4Rate}}</span>' +
'</span>' +
'</div>' +
'</div>' +
'<div class="payband" v-if="showPayBand">' +
'<p class="payband__stat"><span class="payband__label">Miles to next pay increase:</span> <span class="payband__amount">{{payBandMiles}}</span></p>' +
'<p class="payband__description"><span>* SOLO = $0.01/mi</span><span>* TEAM = $0.005/mi</span></p>' +
'</div>' +
'</div>' +
'</div>'
});
(window.onload = function() {
var SmartDriveScore = 0;
storageWrap.setAdaptor(sessionStorage); // default to session storage
if (_greentin_app_config.displayPage === 'dashboard') {
if (_greentin_app_config.started !== true) {
// performance check
_greentin_app_config.started = true; // sets performance flag
new Vue({
el: _greentin_app_config.targetEl,
mounted: function() {
this.SmartDriveScore = 99999;
},
template:
'<div class="greeting-portlet">' +
' <div class="grid-x grid-margin-x">' +
' <div class="cell small-12 large-5"><greeting-portlet-text></greeting-portlet-text></div>' +
' <div class="cell small-12 large-7"><greeting-portlet-progress></greeting-portlet-progress></div>' +
' <div class="cell small-12 hide-for-large"><greeting-portlet-buttons-panel></greeting-portlet-buttons-panel></div>' +
' </div>' +
'</div>'
});
}
} else {
new Vue({
el: '#bonus-progress-wrapper',
template:
'<div class="default-view"><greeting-portlet-text></greeting-portlet-text>' +
'<greeting-portlet-progress></greeting-portlet-progress></div>'
});
}
})();

Related

How to update the text of a Tinymce text component?

I have the following situation, I have a listing where if I press brings me the text to the text editor, the issue arises when I want to add more text and this is bugged in an endless cycle killing Vue, I do not know if it is wrongly done or not.
Tinymce Component
<template>
<div>
<editor
:id="uuid"
api-key="xxxxxxxx"
:init="editorInit"
v-model="content"
/>
</div>
</template>
<script>
import Editor from '#tinymce/tinymce-vue'
export default {
name: "tinymce",
components: {
'editor': Editor
},
props: ['resultsEditor','clearcomponent','uuidEditor','size','setContentText'],
data() {
return {
uuid: this.uuidEditor,
content: null,
editorInit: {
height: this.size,
menubar: false,
entity_encoding: 'raw',
language: 'es',
plugins: ['image', 'advlist', 'autolink', 'lists', 'link', 'charmap', 'preview', 'anchor',
'searchreplace', 'visualblocks', 'code', 'fullscreen', 'insertdatetime', 'media', 'table',
'help', 'wordcount'
],
toolbar: 'undo redo | image | blocks | bold | alignleft aligncenter alignright alignjustify | bullist numlist | table ', // | removeformat', //outdent indent => incrementar sangría
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }',
branding: false,
relative_urls: false,
remove_script_host : false,
document_base_url : window.location.origin,
automatic_uploads: true,
resize_img_proportional: true,
setup: function(editor) {
editor.on('init', function(args) {
editor = args.target;
editor.on('NodeChange', function(e) {
if (e && e.element.nodeName.toLowerCase() == 'img') {
var width = 0;
var height = 0;
width = e.element.width
height = e.element.height
if (width > 800) {
height = height / (width / 800);
width = 800;
}
tinyMCE.DOM.setAttribs(e.element, {
'width': width,
'height': height
});
}
});
});
},
images_upload_handler: (blobInfo) => {
return new Promise((success, failure) => {
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', route('upload_image_no_attach'));
xhr.onload = function() {
var json;
if (xhr.status != 200) {
reject('HTTP Error: ' + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
reject('Invalid JSON: ' + xhr.responseText);
return;
}
// success(json.location);
if (xhr.status === 200) {
const location =
`${window.location.origin}/opportunity/preview/${json.location}`;
success(location)
}
};
formData = new FormData();
formData.append('image', blobInfo.blob(), blobInfo.filename());
xhr.send(formData);
});
}
}
}
},
watch: {
content: function (newValue, oldValue){
this.resultsEditor(this.content)
},
clearcomponent: function(){
if (this.clearcomponent) {
tinyMCE.get(this.uuidEditor).setContent('');
this.content = null
}
},
setContentText: function(){
// console.log(this.setContentText)
if (this.setContentText != '') {
tinyMCE.get(this.uuidEditor).setContent(this.setContentText);
this.content = this.setContentText //Problem to update data to other component.
}
}
}
}
</script>
Modal Template Component
<!-- LISTADO DE PLANTILLAS -->
<b-list-group class="mt-2 search-width scroll-custom-template" v-if="listTemplates.length > 0">
<b-list-group-item
v-for="data in filterByList" :key="data.id"
class="with-coursor"
:active="textID == data.id"
#click="selectTemplate(data)"
>{{ data.name }}</b-list-group-item>
</b-list-group>
<!-- END LISTADO DE PLANTILLAS -->
</div>
<div class="col-sm-9 col-md-9 col-lg-9">
<tinymce
uuidEditor="template_opportunity"
size="450"
:setContentText="text"
:clearcomponent="this.clearContent"
:resultsEditor="onResultsEditor"
></tinymce>
</div>
onResultsEditor(text){
// this.text = text //It writes the text in it from left to left and not from left to right.
},
Example:
This is my original template that I select:
Hello world, you are in europe :D.
This is what it writes me when I fill in the input and I want to update.
The word is: Nuevo
oveuHello world, you are in europe :D.N

Datatable.Net - Search by columns is not rendering

I'm using jQuery datatable.net to render a table (server-side). Everything including filtering is working fine. I elected to implement searching by column and I just can't seem to get it to render the values. When I type in a value, the "Processing" window displays and immediately goes away (which tells me that the search string is being processed) however the search results are not being displayed.
My datatable script is as follows:
#section scripts {
<script type="text/javascript">
$(document).ready(function () {
$('#contacts tfoot th').each(function () {
var title = $(this).text();
$(this).html('<input type="text" placeholder="Search ' + title + '" />');
});
var contactlist = $('#contacts').DataTable({
responsive: true,
destroy: true,
orderMulti: true,
processing: true,
serverSide: true,
stateSave: true,
stateSaveCallback: function (settings, data) {
localStorage.setItem('DataTables_' + settings.sInstance, JSON.stringify(data))
},
stateLoadCallback: function (settings) {
return JSON.parse(localStorage.getItem('DataTables_' + settings.sInstance))
},
oLanguage: {
sSearch: ""
},
pagingType: "full_numbers",
filter: true,
rowId: "id",
order: [[1, "asc"]],
ajax: {
url: "/Contact/GetContactList",
type: "POST",
datatype: "json"
},
columnDefs: [{
targets: [0],
visible: false,
searchable: false
}],
"columns": [
{ data: "id", name: "Id", autoWidth: true},
{ data: "firstName", name: "FirstName", autoWidth: true },
{ data: "lastName", name: "LastName", autoWidth: true },
{ data: "company", name: "Company", autoWidth: true },
{
data: null,
name: "Phone",
autoWidth: true,
defaultContent: "",
render: function (data, type, row) {
var cell = "";
var office = "";
var other = "";
if (row.phoneCell != null) {
cell = "<i class='fas fa-mobile-alt'></i><a href='tel:" + row.phoneCell + "'> " + "<small>" + row.phoneCell + "</small></a>";
}
if (row.phoneOffice != null) {
if (cell != "") { office = "<br />"; }
office = office + "<i class='fas fa-building'></i><a href='tel:" + row.phoneOffice + "'> " + "<small>" + row.phoneOffice + "</small></a>";
}
if (row.phoneOther != null) {
if (office != "") { other = "<br />"; }
other = other + "<i class='fas fa-phone-square-alt'></i><a href='tel:" + row.phoneOther + "'> " + "<small>" + row.phoneOther + "</small></a>";
}
return cell + office + other;
}
},
{
data: "webSite",
name: "WebSite",
autoWidth: true,
defaultContent: "",
render: function (data, type, row) {
if (row.webSite != null) {
return "<i class='fas fa-globe-americas'></i><a href='" + row.webSite + "' target='_blank'> " + "<small>" + row.webSite + "</small></a>";
}
}
},
{ data: "campaign", name: "Campaign", autoWidth: true, defaultContent: "" },
],
initComplete: function () {
var r = $('#contacts tfoot tr');
r.find('th').each(function () {
$(this).css('padding', 8);
});
$('#contacts thead').append(r);
$('#search_0').css('text-align', 'center');
var api = this.api();
api.columns().every(function () {
var that = this;
$('input', this.footer()).on('keyup change', function () {
if (that.search() !== this.value) {
that.search(this.value);
that.draw();
}
});
});
}
});
$('.dataTables_filter input[type="search"]').
attr('placeholder', 'Filter by first/last name or company ...').
css({ 'width': '350px', 'display': 'inline-block' });
$('#contacts tbody').on('click', 'tr', function () {
debugger;
var currentRowData = contactlist.row(this).data();
var id = currentRowData.id;
var url = "#Url.Action("View", "Contact")?id=" + id;
window.open(url,"_parent");
});
});
</script>
Any idea what I'm doing wrong?
Thanks.
-- Val

Why is Babel throwing an error in my vue.js component?

<template>
<div emptyDiv>
<h3> Stages </h3>
<table :style="tableStyle">
<tbody>
<template v-for="item in jobs">
<tr>
<td v-for="stage in item.stage_exec" :style="getStyle(stage.build_id)" :title="stage.build_id" >
[[ stage.cleanDuration ]]
</td>
</tr>
</template>
</tbody>
</table>
</div>
</template>
<script>
import Vue from 'vue';
import moment from 'moment';
export default {
delimiters: [ '[[', ']]' ],
props: ['jobs'],
computed: {
tableStyle() {
return {
'background-color': '#f9f9f9',
'border-color': '#C0C0C0',
'padding': '8px',
'width': '100%',
'display': 'table',
'table-layout': 'fixed',
};
},
emptyDiv() {
return {
'display': 'contents',
};
},
},
methods: {
getStyle (name) {
switch (name) {
case 'SUCCESS':
return {
'background-color': '#dff0d8',
'padding': '10px',
'line-height': '1.42857143',
'border': '1px solid #C0C0C0',
}
case 'FAILURE':
return {
'background-color': '#f45942',
'padding': '10px',
'line-height': '1.42857143',
'border': '1px solid #C0C0C0',
}
}
},
},
filters: {
durationReadable: function(duration) {
milliseconds = parseInt((duration%1000)/100)
seconds = parseInt((duration/1000)%60)
minutes = parseInt((duration/(1000*60))%60)
if (minutes < 10) {
minutes = '0' + minutes
}
if (seconds < 10){
seconds = '0' + seconds
}
return minutes + " m " + seconds + " s " + milliseconds + ' ms'
}
},
created() {
testEndpoint = 'http://testurl'
fetch(testEndpoint)
.then(body => {
cleanStartTime = moment(body[0].time_start)
cleanEndTime = moment(body[0].time_end)
cleanDuration = this.calculateDuration(cleanStartTime, cleanEndTime)
this.job_execs.push({
'name': body[0].job.name,
'build_id': body[0].build_id,
'env': body[0].job.env,
'time_start': cleanStartTime.format('LLL'),
'time_end': cleanEndTime.format
})
})
.catch( err => {
this.isEmpty = (this.binaries.length == 0) ? true : false;
console.log('Error Fetching:', testEndpoint, err);
return { 'failure': testEndpoint, 'reason': err };
},
},
</script>
When I try to serve my component, it is failing to compile and I keep getting a babel error that I cannot figure out.
Unexpected token (117:2)
115 | return { 'failure': testEndpoint, 'reason': err };
116 | },
> 117 |
Unexpected token (117:2)
115 | return { 'failure': testEndpoint, 'reason': err };
116 | },
> 117 | },
| ^
118 | };
119 |
So what is the unexpected token?

Creating Vue Search Bar | How to hide/show data based on input?

I am creating a dynamic search bar that will filter a sidebar full of names based on user input. However, I am having trouble temporarily hiding and showing data based on the search bar's value on keyup. What is the best way to achieve this the "Vue way"?
On keyup, I want to filter through all of the this.people data and only show names that contain the value of the search input.
Below is what my code looks like
Vue.component('sidebar',{
props: ['people', 'tables'],
data: () => {
return {
fullName: ''
}
},
computed: {
computed() {
return [this.people, this.tables].join()
}
},
template:
`
<div id="sidebarContain" v-if="this.people">
<input id="sidebar-search" type="text" placeholder="Search..." #keydown="searchQuery">
<select id="sidebar-select" #change="sidebarChanged">
<option value="AZ">A-Z</option>
<option value="ZA">Z-A</option>
<option value="notAtTable">No Table</option>
<option value="Dean's Guest">Dean's Guest</option>
<option value="BOO | VIP">BOO | VIP</option>
</select>
<div v-for="person in people" :class="[{'checked-in': isCheckedIn(person)}, 'person']" :id="person.id" :style="calcRegColor(person)">
<span v-if="person.table_name">{{person.first_name + ' ' + person.last_name + ' - ' + person.table_name}}</span>
<span v-else>{{person.first_name + ' ' + person.last_name}}</span>
</div>
</div>
`,
methods: {
isCheckedIn(person) {
return person.reg_scan == null ? true : false;
},
isHidden(person)
{
console.log("here");
},
calcRegColor(person)
{
switch(person.registration_type)
{
case "Dean's Guest" :
return {
color: 'purple'
}
break;
case "BOO | VIP" :
return {
color: 'brown'
}
break;
case "Student" :
return {
color: 'green'
}
break;
case "Faculty":
case "Staff":
return {
color: 'blue'
}
break;
case "Alumni Club Leader":
return {
color: 'gold'
}
break;
case "Table Guest" :
return {
color: 'pink'
}
break;
default:
return {
color: 'black'
}
}
}
},
watch: {
computed() {
console.log("People and Tables Available");
}
}
});
var app = new Vue({
el: '#main',
data: {
tables: {},
people: [],
currentAlerts: [],
lastDismissed: []
},
methods: {
loadTables() {
$.ajax({
method: 'POST',
dataType: 'json',
url: base_url + 'users/getTableAssignments/' + event_id
}).done(data => {
this.tables = data;
});
},
loadPeople() {
$.ajax({
method: 'POST',
dataType: 'json',
url: base_url + 'users/getParticipants2/' + event_id
}).done(data => {
this.people = data;
this.sortSidebar(this.people);
});
},
loadCurrentAlerts() {
$.ajax({
method: 'POST',
dataType: 'json',
url: base_url + 'alerts/getAlerts/' + event_id
}).done(data => {
this.currentAlerts = data;
});
},
loadLastDismissed(num = 15)
{
$.ajax({
method: 'POST',
dataType: 'json',
url: base_url + 'alerts/getLastDismissed/' + event_id + '/' + num
}).done(data => {
this.lastDismissed = data;
});
},
setRefresh() {
setInterval(() => {
console.log("Getting People and Tables");
this.loadPeople();
this.loadTables();
}, 100000);
},
makeTablesDraggable() {
$(document).on("mouseenter", '.table', function(e){
var item = $(this);
//check if the item is already draggable
if (!item.is('.ui-draggable')) {
//make the item draggable
item.draggable({
start: (event, ui) => {
console.log($(this));
}
});
}
});
},
makePeopleDraggable() {
$(document).on("mouseenter", '.person', function(e){
var item = $(this);
//check if the item is already draggable
if (!item.is('.ui-draggable')) {
//make the item draggable
item.draggable({
appendTo: 'body',
containment: 'window',
scroll: false,
helper: 'clone',
start: (event, ui) => {
console.log($(this));
}
});
}
});
}
makeDroppable() {
$(document).on("mouseenter", ".dropzone, .table", function(e) {
$(this).droppable({
drop: function(ev, ui) {
console.log("Dropped in dropzone");
}
});
});
}
},
mounted() {
this.loadTables();
this.loadPeople();
this.loadCurrentAlerts();
this.loadLastDismissed();
this.setRefresh();
this.makeTablesDraggable();
this.makePeopleDraggable();
this.makeDroppable();
}
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
</head>
<div id="app">
<sidebar :people="people" :tables="tables"></sidebar>
</div>
You can change the people property in sidebar into a computed property, which will be calculated based on user's input.
So change the sidebar code to
<div v-for="person in filteredPeople" :class="[{'checked-in': isCheckedIn(person)}, 'person']" :id="person.id" :style="calcRegColor(person)">
<span v-if="person.table_name">{{person.first_name + ' ' + person.last_name + ' - ' + person.table_name}}</span>
<span v-else>{{person.first_name + ' ' + person.last_name}}</span>
</div>
and add a computed property
computed: {
filteredPeople () {
// Logic to filter data
}
}
A foolish aproach that I use, without computed properties:
JS:
new Vue({
el: '#app',
data: {
list: [],
filteredList: []
},
mounted(){
this.filteredList = this.list
},
methods: {
filter(e){
if(e.target.value === '') this.filteredList = this.list
else {
this.filteredList = []
this.list.forEach(item=>{
if(list.name.includes(e.target.value)) this.filteredList.push(item)
})
}
}
}
})
The "name" property of list object can be changed to whatever property you want to look for.
HTML:
<input #keyup="filter" id="search" type="search" required>

How to use postCreate in Dojo?

I am testing post create so I can set up class properties in postcreate rather than calling here
request("js/my/data/sample.json", {
handleAs: "json"
}).then(function (jsonResults) {
arrayUtil.forEach(jsonResults.LinksMap, function (List) {
arrayUtil.forEach(List.LinksMap.entry, function (Ientry) {
if ('information' === Ientry.linkType) Ientry.className = 'info';
else if ('news link' === Ientry.linkType) Ientry.className = 'news';
var widget = new support(Ientry).placeAt(authorContainer);
});
});
});
I tried
postCreate: function () {
this.inherited(arguments);
},
_setLinkClssAttr: function (iconClass) {
if (iconClass != "") {
if ('information' === linkType) LinkClss = 'info';
if ('news link' === Ientry.linkType) LinkClss = 'news';
this._set("LinkClss", iconClass);
this.LinkNode.class = iconClass;
}
}
my HTML template looks like this
<a class="${baseClass}LinkClss" href="${Link.url}" data-dojo-attach-point="LinkNode">${Link.title}</a>
Is this what you mean?
HTML code:
<div id="myWidget1"></div>
<div id="myWidget2"></div>
<div id="myWidget3"></div>
CSS:
.info {
color: red;
}
.news {
color: blue;
}
Code to create the Widget, passing in an entry object:
require([
"dojo/parser", "dojo/dom", "MyWidget", "dojo/domReady!"],
function (parser, dom, MyWidget) {
console.log(arguments);
parser.parse().then(function () {
var linkTypes = ['information', 'news link', 'other'];
linkTypes.forEach(function (linkType, i) {
var entry = {
link: 'hello' + (i + 1),
linkType: linkType,
linkHref: "https://www.google.co.uk/search?q=" + linkType
};
new MyWidget(entry, dom.byId("myWidget" + (i + 1)));
});
});
});
Code to define the widget:
define("MyWidget", [
"dojo/_base/declare", "dojo/dom-class", "dojo/dom-attr", "dojo/query",
"dijit/_WidgetBase", "dijit/_TemplatedMixin", "dojo/NodeList-dom"],
function (declare, domClass, domAttr, query, _WidgetBase, _TemplatedMixin) {
var template = [
'<div>',
'<a data-dojo-attach-point="linkNode"></a>',
'</div>'];
return declare("MyWidget", [_WidgetBase, _TemplatedMixin], {
templateString: template.join("\n"),
constructor: function (params, srcNodeRef) {
console.log("creating widget with params " + dojo.toJson(params) +
" on node " + srcNodeRef);
},
postCreate: function () {
console.log(arguments);
this.inherited(arguments);
this._setLinkClass();
},
// private methods
_setLinkClass: function () {
var linkClass = this._calculateLinkClass();
console.log(linkClass, this.linkNode);
if (linkClass != "") {
query(this.linkNode).addClass(linkClass);
}
},
_calculateLinkClass: function () {
var linkClass = "";
if ('information' === this.linkType) linkClass = 'info';
if ('news link' === this.linkType) linkClass = 'news';
return linkClass;
},
// Attributes
link: "empty",
_setLinkAttr: {
node: "linkNode",
type: "innerHTML"
},
linkHref: "#",
_setLinkHrefAttr: function (href) {
domAttr.set(this.linkNode, "href", href);
}
});
});
Result: