showing encoded emoji in Angular2 - javascript

I am performing a loop on angular2 with dynamic emoji values encoded with org.apache.commons:commons-lang3 library in android like \uD83D\uDEB5\uD83D\uDEB5\uD83D\uDEB5. I need to decode them in angular2 frontend. In itemsArr[index]['Posted Content'] = item[0]['document']['post_content']; I get the encoded content from backend. And
this is how I am trying to show them
Code as follows
ngOnInit() {
this.loading = true;
var itemsArr = [];
var reporterPromiseArr = [];
var postPromiseArr = [];
var posts = this._cb.getRelationalDataFromTable('reportPost').then(res => {
res.forEach(item => {
itemsArr.push({ 'Reported On': item.document.createdAt, 'Posted By': '', 'Posted On': '', 'postId': item.document.post_id });
postPromiseArr.push(this._cb.getRelationalDataFromTableNew('userActivityStream', [{ key: '_id', value: item.document.post_id }], ['product_id', 'user_id']));
reporterPromiseArr.push(this._cb.getRelationalDataFromTable('registration', [{ key: '_id', value: item.document.user_id }]));
});
return Promise.all(postPromiseArr);
}).then(res => {
res.forEach((item, index) => {
itemsArr[index]['Posted By'] = (item[0]['document']['user_id'] !== null) ? item[0]['document']['user_id']['document']['user_name'] : '';
itemsArr[index]['Posted On'] = item[0]['document']['createdAt'];
itemsArr[index]['Posted Type'] = item[0]['document']['type'];
itemsArr[index]['Total Likes'] = item[0]['document']['total_like'];
itemsArr[index]['Posted Content'] = item[0]['document']['post_content'];
itemsArr[index]['Image'] = decodeURI(item[0]['document']['image']);
});
//console.log(reporterPromiseArr);
return Promise.all(reporterPromiseArr);
}).then(res => {
res.forEach((item, index) => {
itemsArr[index]['Reported By'] = item[0]['document']['user_name'];
});
this.listingArr = itemsArr;
this.loading = false;
}).catch(err => {
this.loading = false;
console.log(err)
});
console.log(itemsArr);
//return Promise.all(reporterPromiseArr);
}
html as follows where i tried to show them in innerHTML but not working
<form class="tr" #requestData="ngForm" (ngSubmit)="onSubmit(requestData)" *ngFor="let item of listingArr; let i = index">
<div class="td">{{i + 1}}</div>
<div class="td">{{ item['Reported By'] }}</div>
<div class="td">{{item['Reported On'] | date: yMMMdjms }}</div>
<div class="td">{{ item['Posted By'] }}</div>
<div class="td">{{ item['Posted On'] | date: yMMMdjms }}</div>
<div class="td">{{ (item['Total Likes'] == null)?0:item['Total Likes'] }}</div>
<div class="td">{{ item['Posted Type'] }}</div>
<div [innerHTML]="item['Posted Content']"></div>
</div>
</form>

If you need them to be displayed properly on the page, you need to bind them with innerHTML in Angular2
<div [innerHTML]="the.path.to.property"></div>

Related

How to save updated an embedded picklist selection on a custom Lightning Datatable?

I am using a 'Custom Datatable' solution in order to modify picklist values within a datatable. Project code may be referenced here:
https://live.playg.app/play/picklist-in-lightning-datatable
I have made changes so that I can retrieve data from the custom object: Payment__c, and I am attempting modify the picklist values for the Payment_Status__c field. My 'debugging' method has been to create numerous console.log statements to verify data during the updating process. Picklist values are currently hardcoded (have not figured out how to dynamically pull from SF yet). Inline edit of individual cells works fine, and I am able to save those values as well (though changes are not reflected until I perform a manual page refresh). Picklist selection is working, but I am unable to save the currently selected picklist value in the datatable.
I believe that the intended trigger event for picklist selection changes--'valueselect', is not being fired, and the handleSelection method is not receiving this event when a new picklist selection is made.
The lightning component used on Salesforce is c-customDatatableDemo:
customDatatableDemo.js
import { LightningElement, track, wire } from 'lwc';
import getPayments from '#salesforce/apex/PaymentController.getPayments';
import saveRecords from '#salesforce/apex/PaymentController.saveRecords';
import { updateRecord } from 'lightning/uiRecordApi';
import { refreshApex } from '#salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
export default class CustomDatatableDemo extends LightningElement {
#track data = [];
//have this attribute to track data changed
//with custom picklist or custom lookup
#track draftValues = [];
#track lastSavedData = [];
connectedCallback() {
this.columns = [
{
label: 'Name',
fieldName: 'Name',
editable: false
}, {
label: 'Invoice Number',
fieldName: 'Invoice_Number__c',
editable: true
}, {
label: 'Invoice Amount',
fieldName: 'Invoice_Amount__c',
type: 'currency',
editable: true
}, {
label: 'Invoice Date',
fieldName: 'Invoice_Date__c',
type: 'date',
editable: true
}, {
label: 'Payment Status',
fieldName: 'Payment_Status__c',
type: 'picklist',
typeAttributes:
{
placeholder: 'Choose Status',
options: [
{ label: 'Needs to Be Paid', value: 'Needs to Be Paid' },
{ label: 'Issued', value: 'Issued' },
{ label: 'Voided', value: 'Voided' },
] // List of Payment Status picklist options
, value: {fieldName: 'Payment_Status__c' } // default value for picklist
, context: {fieldName: 'Id' } // binding Payment Id with context variable to be returned back
}
},
{
label: 'Description', fieldName: 'Work_Description__c', type: 'text', editable: true
}];
// Get Payments data
getPayments()
.then(result => {
this.data = result;
this.error = undefined;
})
.catch(error => {
this.error = error;
this.data = undefined;
})
// Save last saved copy
this.lastSavedData = JSON.parse(JSON.stringify(this.data));
}
updateDataValues(updateItem) {
console.log('START--updateDataValues()');
let copyData = [... this.data];
copyData.forEach(item => {
if (item.Id === updateItem.Id) {
for (let field in updateItem) {
console.log('updateDataValues() item.Id = ' + JSON.stringify(updateItem.Id));
console.log('updateItem[field] = ' + JSON.stringify(updateItem[field]));
item[field] = updateItem[field];
console.log('UPDATED--item[field] = ' + updateItem[field]);
}
}
});
//write changes back to original data
this.data = [...copyData];
console.log('this.data = ' + JSON.stringify(this.data));
let tempData = [...this.data];
//console.log('tempData = ' + JSON.stringify(tempData));
console.log('END--updateDataValues()');
}
updateDraftValues(updateItem) {
console.log('START--updateDraftValues()');
console.log('stringify draft updateItem = ' + JSON.stringify(updateItem));
let draftValueChanged = false;
let copyDraftValues = [...this.draftValues];
//store changed value to do operations
//on save. This will enable inline editing &
//show standard cancel & save button
let i = 0;
copyDraftValues.forEach(item => {
if (item.Id === updateItem.Id) {
i++;
console.log('i = ' + i);
for (let field in updateItem) {
console.log(i + '. UpdateDraftValues--item id if selected...item Id = ' + item.Id + ' & item value = ' + item.value);
item[field] = updateItem[field];
console.log('item[field] = ' + updateItem[field]);
}
draftValueChanged = true;
console.log('draftValueChanged = TRUE');
}
});
//draftValueChanged = true;
if (draftValueChanged) {
console.log('YESdraftValueChanged');
console.log('copyDraftValues = ' + JSON.stringify(copyDraftValues));
this.draftValues = [...copyDraftValues];
//console.log('draftValues = ' + JSON.stringify(draftValues));
} else {
console.log('NOdraftValue!Changed');
this.draftValues = [...copyDraftValues, updateItem];
let testDraftValues = {... this.draftValues};
console.log('JSON.stringify(testDraftValues) = ' + JSON.stringify(testDraftValues));
}
console.log('STOP--updateDraftValues()')
}
//listener handler to get the context and data
//updates datatable
picklistChanged(event) {
console.log('START--picklistChanged()');
console.log('EVENT type - ' + event.type);
event.stopPropagation();
let dataReceived = event.detail.data;
let updatedItem = { ...dataReceived };
console.log('picklistChanged()...updatedItem = ' + JSON.stringify(updatedItem));
this.updateDraftValues(updatedItem);
this.updateDataValues(updatedItem);
/* console.log('event.value = ' + event.value);
this.value = event.target.value;
event.stopPropagation();
let dataReceived = event.detail.data;
let updatedItem = { ...dataReceived };
console.log('updatedItem.context ' + updatedItem.context);
console.log('updatedItem.value ' + updatedItem.value);
console.log('updatedItem = ' + JSON.stringify(updatedItem));
this.updateDraftValues(updatedItem);
this.updateDataValues(updatedItem);
console.log('picklistChanged() = ' + JSON.stringify(updatedItem)); */
console.log('STOP--picklistChanged()');
}
handleSelection(event) {
console.log('START--handleSelection()');
this.updateDraftValues(event.detail.draftValues[0]);
console.log('this.updateDraftValues(event.detail.draftValues[0]);')
/* event.stopPropogation();
let dataReceived = event.detail.data;
let updatedItem = { ...dataReceived };
this.updateDraftValues(updatedItem);
this.updateDraftValues(updatedItem); */
console.log('STOP--handleSelection() = ' + JSON.stringify(updatedItem));
}
//handler to handle cell changes & update values in draft values
handleCellChange(event) {
console.log('START--handleCellChange()');
console.log('handleCellChange');
this.updateDraftValues(event.detail.draftValues[0]);
console.log('handleCellChange value = ' + JSON.stringify(this.updateDraftValues));
console.log('END--handleCellChange()');
}
handleSave(event) {
if (event.type === 'picklistchanged'){
}
console.log('START--handleSave');
console.log('Updated items = ', this.draftValues);
// save last saved copy
this.lastSavedData = JSON.parse(JSON.stringify(this.data));
console.log('this.lastSavedData = ' + JSON.stringify(this.lastSavedData));
this.fldsItemValues = event.detail.draftValues;
console.log('this.fldsItemValues = ' + JSON.stringify(this.fldsItemValues));
const inputsItems = this.fldsItemValues.slice().map(draft => {
const fields = Object.assign({}, draft);
console.log('JSON.stringify() fields ' + JSON.stringify(fields));
return { fields };
});
// Show toast after successful update
const promises = inputsItems.map(recordInput => updateRecord(recordInput));
Promise.all(promises).then(res => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Success',
message: 'Records Updated Successfully!!',
variant: 'success'
})
);
this.fldsItemValues = [];
return this.refresh();
}).catch(error => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error',
message: 'An Error Occured!!',
variant: 'error'
})
);
}).finally(() => {
// Clear draft values
this.draftValues = [];
});
// Refresh the window after successful save
//window.open('url','_self');
//document.location.reload(true);
//cmp.find("table-component-id").set("v.draftValues", null);
console.log('END--handleSave');
}
handleCancel(event) {
//remove draftValues & revert data changes
this.data = JSON.parse(JSON.stringify(this.lastSavedData));
this.draftValues = [];
}
async refresh() {
console.log('async refresh');
await refreshApex(this.data);
//this.connectedCallback();
}
}
customDatatableDemo.html
<template>
<lightning-card title="Invoicing" icon-name="custom:custom17">
<div class="slds-var-m-around_medium">
<template if:true={data}>
<c-custom-data-table
object-api-name="Payment__c"
key-field="Id"
data={data}
value=""
show-row-number-column
columns={columns}
onpicklistchanged={picklistChanged}
onvalueselect={handleSelection}
draft-values={draftValues}
oncellchange={handleCellChange}
onsave={handleSave}
oncancel={handleCancel}>
</c-custom-data-table>
<template if:true={data.error}></template>
</template>
</div>
</lightning-card>
<p>Selected value is: {value}</p>
</template>
customDataTable.js
import LightningDatatable from 'lightning/datatable';
//import the template so that it can be reused
import DatatablePicklistTemplate from './picklist-template.html';
import { loadStyle } from 'lightning/platformResourceLoader';
import CustomDataTableResource from '#salesforce/resourceUrl/CustomDataTable';
export default class CustomDataTable extends LightningDatatable {
static customTypes = {
picklist: {
template: DatatablePicklistTemplate,
typeAttributes: ['label', 'placeholder', 'options', 'value', 'context'],
},
};
constructor() {
super();
Promise.all([
loadStyle(this, CustomDataTableResource),
]).then(() => {})
}
}
picklist-template.html (Same folder as customDataTable)
<template>
<c-datatable-picklist label={typeAttributes.label} value={typeAttributes.value}
placeholder={typeAttributes.placeholder} options={typeAttributes.options} context={typeAttributes.context}>
</c-datatable-picklist>
</template>
datatablePicklist.js
import { LightningElement, api, track } from 'lwc';
export default class DatatablePicklist extends LightningElement {
#api label;
#api placeholder;
#api options;
#api value;
#api context;
handleChange(event) {
//show the selected value on UI
this.value = event.detail.value;
//fire event to send context and selected value to the data table
this.dispatchEvent(new CustomEvent('picklistchanged', {
composed: true,
bubbles: true,
cancelable: true,
detail: {
data: { context: this.context, value: this.value }
}
}));
}
}
datatablePicklist.html
<template>
<div class="picklist-container">
<lightning-combobox name="picklist" label={label} value={value} placeholder={placeholder} options={options}
onchange={handleChange}></lightning-combobox>}
</div>
</template>
lwcEditSaveRow.js
import { LightningElement, wire, track } from 'lwc';
import getAccounts from '#salesforce/apex/lwcEditSaveRowCtrl.getAccounts';
import { updateRecord } from 'lightning/uiRecordApi';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { refreshApex } from '#salesforce/apex';
const columns = [
{
label: 'Name',
fieldName: 'Name',
type: 'text',
}, {
label: 'Phone',
fieldName: 'Phone',
type: 'phone',
editable: true,
}, {
label: 'Industry',
fieldName: 'Industry',
type: 'text',
editable: true,
}, {
label: 'Type',
fieldName: 'Type',
type: 'text',
editable: true
}, {
label: 'Description',
fieldName: 'Type',
type: 'text',
editable: true
}
];
export default class LwcEditSaveRow extends LightningElement {
columns = columns;
#track accObj;
fldsItemValues = [];
#wire(getAccounts)
cons(result) {
this.accObj = result;
if (result.error) {
this.accObj = undefined;
}
};
saveHandleAction(event) {
this.fldsItemValues = event.detail.draftValues;
const inputsItems = this.fldsItemValues.slice().map(draft => {
const fields = Object.assign({}, draft);
return { fields };
});
const promises = inputsItems.map(recordInput => updateRecord(recordInput));
Promise.all(promises).then(res => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Success',
message: 'Records Updated Successfully!!',
variant: 'success'
})
);
this.fldsItemValues = [];
return this.refresh();
}).catch(error => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error',
message: 'An Error Occured!!',
variant: 'error'
})
);
}).finally(() => {
this.fldsItemValues = [];
});
}
async refresh() {
await refreshApex(this.accObj);
}
}
lwcEditSaveRow.html
<template>
<lightning-card>
<div class="slds-m-around_medium">
<h3 class="slds-text-heading_medium"><lightning-icon icon-name="custom:custom84" size="small"></lightning-icon> <strong style="color:#270086; font-size:13px; margin-right:5px;"> How to inline Edit/Save Rows With Lightning Datatable in Lightning Web Component (LWC) </strong></h3>
<br/><br/>
<template if:true={accObj.data}>
<lightning-datatable key-field="Id"
data={accObj.data}
columns={columns}
onsave={saveHandleAction}
draft-values={fldsItemValues}
hide-checkbox-column
show-row-number-column>
</lightning-datatable>
</template>
<br/>
<br/>
<!--Start RelatedTopics Section-->
<div style="border:1px #ddd solid; padding:10px; background:#eee; margin:40px 0;">
<p data-aura-rendered-by="435:0"><img src="https://www.w3web.net/wp-content/uploads/2021/05/thumbsUpLike.png" width="25" height="25" style="vertical-align:top; margin-right:10px;" data-aura-rendered-by="436:0"><strong data-aura-rendered-by="437:0"><span style="font-size:16px; font-style:italic; display:inline-block; margin-right:5px;">Don't forget to check out:-</span>An easy way to learn step-by-step online free Salesforce tutorial, To know more Click <span style="color:#ff8000; font-size:18px;" data-aura-rendered-by="442:0">Here..</span></strong></p>
<br/><br/>
<p data-aura-rendered-by="435:0"><img src="https://www.w3web.net/wp-content/uploads/2021/07/tickMarkIcon.png" width="25" height="25" style="vertical-align:top; margin-right:10px;" data-aura-rendered-by="436:0"><strong data-aura-rendered-by="437:0"><span style="font-size:17px; font-style:italic; display:inline-block; margin-right:5px; color:rgb(255 128 0);">You May Also Like →</span> </strong></p>
<div style="display:block; overflow:hidden;">
<div style="width: 50%; float:left; display:inline-block">
<ul style="list-style-type: square; font-size: 16px; margin: 0 0 0 54px; padding: 0;">
<li>How to get selected checkbox value in lwc</li>
<li>how to display account related contacts based on AccountId in lwc</li>
<li>how to create lightning datatable row actions in lwc</li>
<li>how to use if and else condition in lwc</li>
<li>how to display selected radio button value in lwc</li>
</ul>
</div>
<div style="width: 50%; float:left; display:inline-block">
<ul style="list-style-type: square; font-size: 16px; margin: 0 0 0 54px; padding: 0;">
<li>display account related contacts based on account name in lwc</li>
<li>how to insert a record of account Using apex class in LWC</li>
<li>how to get picklist values dynamically in lwc</li>
<li>how to edit/save row dynamically in lightning component</li>
<li>update parent field from child using apex trigger</li>
</ul>
</div>
<div style="clear:both;"></div>
<br/>
<div class="youtubeIcon">
<img src="https://www.w3web.net/wp-content/uploads/2021/11/youtubeIcon.png" width="25" height="25" style="vertical-align:top; margin-right:10px;"/> <strong>TechW3web:-</strong> To know more, Use this <span style="color: #ff8000; font-weight: bold;">Link</span>
</div>
</div>
</div>
<!--End RelatedTopics Section-->
</div>
</lightning-card>
</template>
Example of changing and saving non-picklist value in datatable:
Changing and saving non-picklist value
Example of changing and saving a picklist value:
Changing and saving picklist value (1)
Last bit of console output:
Changing and saving picklsit value (2)
As this is my first time working with Lightning Web components, I would greatly appreciate any assistance you may provide. Thanks in advance.
I was able to get this custom data table component working for something I am developing to effectively bind records as rows. Here 2 differences I notice:
I did not include onvalueselect and oncellchange methods for the component html declaration, only the onpicklistchanged.
You may want to use your custom server side controller method instead of the built-in uiRecordApi->updateRecord one. Something tells me this may not play nice with row data from the data table. In my implementation, I was simply able to pass the draftValues over to the server side method which has a single parameter of list of sObject:
async saveRecords(event){
const updatedFields = event.detail.draftValues;
this.draftValues = [];
this.showSpinner = true
try{
await saveRelatedRecords({sObjs: updatedFields}) // server side save
.then((result) => {
this.updateMessage = result;
})
this.showSpinner = false;
if(this.updateMessage == 'success'){
this.showToast('Success', 'Record(s) Updated', 'success');
} else{
this.showToast('Error', this.updateMessage, 'error');
}
await refreshApex(this._wiredRecordData);
this.unsavedData = this.records;
} catch (error) {
this.showSpinner = false;
this.showToast('Error while updating or refreshing records', error.body.message, 'error');
}
}
In regards to your data not refreshing, I suggest you wire your getPayments method so that you can always get a fresh set from the server side, rather than trying to keep track of and maintain data changes on the client side, something like:
_wiredRecordData;
#wire(getRelatedRecords)
relatedRecords(getRecsResult){
const { data, error } = getRecsResult;
this._wiredRecordData = getRecsResult;
if(data){
this.records = data;
}
}
Then after your success toast in your save method, you can use
await refreshApex(_wiredRecords); and lwc knows to rerender based on the wiring (or at least I think that's how it works.)
Lastly, here is the server side controller method I have to dynamically generate column header information so it does not need to be hard coded into the component. However I did need to modify the custom component a bit to include a new "fieldapi" attribute so that the client side method knows what field to set for the changed value during the onpicklistchanged action.
#AuraEnabled(cacheable=true)
public static String getColumnHeaders(String sObjAPI, String fieldAPIs)
{
List<ColumnHeaderInfo> colHeaders = new List<ColumnHeaderInfo>();
Schema.DescribeSObjectResult sObjDesc = Schema.getGlobalDescribe().get(sObjAPI).getDescribe();
Boolean objIsUpdateable = sObjDesc.isUpdateable();
Map<String, Schema.SObjectField> objFields = sObjDesc.fields.getMap();
for(String field: fieldAPIs.split(','))
{
if(!objFields.keySet().contains(field.toLowerCase())){
continue;
}
Schema.DescribeFieldResult fieldDesc = objFields.get(field).getDescribe();
if(!fieldDesc.isAccessible()){
continue;
}
ColumnHeaderInfo colHeader = new ColumnHeaderInfo();
colHeader.label = fieldDesc.getLabel();
colHeader.fieldName = fieldDesc.getName();
colHeader.editable = fieldDesc.isUpdateable() && sObjDesc.isUpdateable();
colHeader.type_x = fieldDesc.getType().name().toLowerCase();
if(colHeader.type_x == 'picklist')
{
colHeader.type_x = 'picklist';
List<Schema.PicklistEntry> picklistValues = fieldDesc.getPicklistValues();
colHeader.typeAttributes = new TypeAttributes();
colHeader.typeAttributes.options = new List<Option>();
for(Schema.PicklistEntry ple: picklistValues)
{
Option opt = new Option();
opt.value = ple.getValue();
opt.label = ple.getLabel();
colHeader.typeAttributes.options.add(opt);
}
colHeader.typeAttributes.context = new FieldName();
colHeader.typeAttributes.context.fieldName = 'Id';
colHeader.typeAttributes.value = new FieldName();
colHeader.typeAttributes.value.fieldName = fieldDesc.getName();
colHeader.typeAttributes.fieldapi = fieldDesc.getName();
}
// multi-select picklist fields not supported so make them read-only
if(colHeader.type_x == 'multipicklist'){
colHeader.editable = false;
}
colHeaders.add(colHeader);
}
return JSON.serialize(colHeaders).replaceAll('type_x', 'type');
}
private class ColumnHeaderInfo
{
public String label;
public String fieldName;
public String type_x;
public Boolean editable;
public TypeAttributes typeAttributes;
}
private class TypeAttributes
{
public String placeholder;
public List<Option> options;
public FieldName value;
public FieldName context;
public FieldName label;
public FieldName tooltip;
public String fieldapi;
public String target;
}
private class Option
{
public String label;
public String value;
}
private class FieldName
{
public String fieldName;
}

precheck checkboxes depending on the response coming in json form in vuejs

Sorry for my English. I am trying to pre select those checkboxes whos values have been saved in the database. I did it using javascript in vuejs but those selected checkboxes values are not storing in array.
My code is like
role.component.js
getRoleRowData(data) {
this.roleaction = "edit";
this.addrolemodal = true;
console.log(data.role_id);
axios
.post(apiUrl.api_url + "getRolePermissionData", {
role_id: data.role_id
}).then(
result => {
this.permid = result.data;
var list = [];
result.data.forEach(function(value) {
list.push(value.perm_id);
});
var options = list;
for (var i = 0; i < options.length; i++) {
if (options[i]) document.querySelectorAll('input[value="' + options[i] + '"][type="checkbox"]')[0].checked = true;
}
},
error => {
console.error(error);
}
);
this.addrole = data;
},
And role.component.html
<div class="col-md-8">
<b-form-fieldset>
<div class="form" id="demo">
<h6>Permissions</h6>
<span v-for="perm_name_obj in listPermissionData">
<input type="checkbox" class="perm_id" v-bind:value="perm_name_obj.perm_id" name="perm_id" id="perm_name" v-model="checkedPerm_Id"> {{perm_name_obj.perm_name}}<br>
</span>
<span>Checked names: {{ checkedPerm_Id }}</span>
</div>
</b-form-fieldset>
</div>
And the Output
And the Ouput I got
In simple words I want to pre check checkboxes in vuejs of which values are stored in database.
See the following example, using simulation data
var app = new Vue({
el: '#app',
data () {
return {
listPermissionData: [],
checkedPerm_Id: []
}
},
created () {
setTimeout(_=>{
//Here simulates axois to request Permission data
this.listPermissionData = [
{perm_id:1,perm_name:'perm_name1'},
{perm_id:2,perm_name:'perm_name2'},
{perm_id:3,perm_name:'perm_name3'},
{perm_id:4,perm_name:'perm_name4'},
{perm_id:5,perm_name:'perm_name5'}
];
//Here simulates axois to request Selected Permissions (result.data)
var selected = [
{perm_id:2,perm_name:'perm_name2'},
{perm_id:5,perm_name:'perm_name5'}
]
this.checkedPerm_Id = selected.map(o=>o.perm_id)
},1000)
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<div class="form">
<h6>Permissions</h6>
<span v-for="perm_name_obj in listPermissionData">
<input type="checkbox" class="perm_id" v-bind:value="perm_name_obj.perm_id" name="perm_id" id="perm_name" v-model="checkedPerm_Id"> {{perm_name_obj.perm_name}}<br>
</span>
<span>Checked names: {{ checkedPerm_Id }}</span>
</div>
</div>
I solved my problem, here is my code
role.component.js
getRoleRowData(data) {
this.roleaction = "edit";
this.addrolemodal = true;
console.log(data.role_id);
let tempthis = this;
axios
.post(apiUrl.api_url + "getRolePermissionData", {
role_id: data.role_id
}).then(
result => {
this.permid = result.data;
var list = [];
result.data.forEach(function(value) {
//by using tempthis variable we provided the current access to the checkedPerm_Id array which not accessible from out of the function which is getRoleRowData
tempthis.checkedPerm_Id.push(value.perm_id);
list.push(value.perm_id);
});
},
error => {
console.error(error);
}
);
this.addrole = data;
},

vue.js with Laravel pagination and filtering for list

I'm still debating the approach but this is what I have so far. The filters work great but the data list is over 2k items, so some sort of limit is going to need to be applied. The issue is that any limit to the view would have to require a new API pull with any filter being set by any methods I've tried.
My question is should I somehow paginate from the API call or pull all data and paginate with vue? Should I perhaps filter in the backend and apply different API calls or should I use what I have below? The filtering works nicely but I am not clear how I could limit whats displayed yet filter through the entire list then return.
My Vue app and components:
Vue.component('filter', {
props: ['list', 'name'],
template: '#filter-template',
watch: {
selected: function(currentValue) {
this.$dispatch('filter-update', [this.name, currentValue]);
}
}
});
Vue.component('products', {
template: '#product-template',
created() {
this.fetchProducts();
},
data:function(){
return {
products:[],
category: 'All',
collection: 'All',
design: 'All'
}
},
events: {
'push-category': function(id) {
this.category = id;
this.filterProducts();
},
'push-collection': function(id) {
this.collection = id;
this.filterProducts();
},
'push-design': function(id) {
this.design = id;
this.filterProducts();
}
},
computed: {
total: function () {
return this.products.length;
}
},
methods: {
fetchProducts: function() {
this.$http.get('api/internal/products', function(products) {
this.$set('products', products);
});
},
filterProducts: function() {
var parent = this;
var catFilter = [];
var collFilter = [];
var designFilter = [];
// Collect all the bad guys
if(this.category == 'All') {
catFilter = [];
} else {
var key = 'Item_Disc_Group';
filter(key, this.category, catFilter);
}
if(this.collection == 'All') {
collFilter = [];
} else {
var key = 'Collection';
filter(key, this.collection, collFilter);
}
if(this.design == 'All') {
designFilter = [];
} else {
var key = 'Fancy_Color_Intensity';
filter(key, this.design, designFilter);
}
// Hide all the bad guys, show any good guys
for (var i = this.products.length - 1; i >= 0; i--) {
var product = this.products[i];
if(catFilter.indexOf(product) > -1) {
product.On_The_Web = "0";
} else if(collFilter.indexOf(product) > -1) {
product.On_The_Web = "0";
} else if(designFilter.indexOf(product) > -1) {
product.On_The_Web = "0";
} else {
product.On_The_Web = "1";
}
};
function filter(key, active, array) {
for (var i = parent.products.length - 1; i >= 0; i--) {
var product = parent.products[i];
if(product[key] != active) {
array.push(product);
}
};
}
}
}
});
new Vue({
el: '#product-filter',
created() {
this.fetchCategories();
this.fetchCollections();
this.fetchDesigns();
},
methods: {
fetchCategories: function() {
this.$http.get('api/categories', function(categories) {
this.$set('categories', categories);
});
},
fetchCollections: function() {
this.$http.get('api/collections', function(collections) {
this.$set('collections', collections);
});
},
fetchDesigns: function() {
this.$http.get('api/designs', function(designs) {
this.$set('designs', designs);
});
}
},
events: {
'filter-update': function(data) {
if(data[0] == "categories") {
this.$broadcast('push-category', data[1]);
} else if (data[0] == "collections") {
this.$broadcast('push-collection', data[1]);
} else {
this.$broadcast('push-design', data[1]);
}
}
}
});
My markup:
<div id="product-filter">
<filter :list="categories" name="categories"></filter>
<filter :list="collections" name="collections"></filter>
<filter :list="designs" name="designs"></filter>
<div class="clearfix"></div>
<products></products>
<!-- Vue Templates -->
<template id="filter-template">
<div class="form-group col-md-2">
<label>#{{ name }}</label>
<select v-model="selected" class="form-control input-small">
<option selected>All</option>
<option value="#{{ option.navision_id }}" v-for="option in list">#{{ option.name }}</option>
</select>
<span>Selected: #{{ selected }}</span>
</div>
</template>
<template id="product-template">
<div class="row mix-grid thumbnails">
<h1>#{{ total }}</h1>
<div v-for="product in products" v-if="product.On_The_Web == '1'" class="col-md-3 col-sm-6 mix category_1">
<a href="/products/#{{ product.id }}">
<div class="mix-inner">
<img class="img-responsive" src="https://s3-us-west-1.amazonaws.com/sg-retail/images/products/#{{ product.No }}.jpg" alt="">
<div class="prod-details">
<h3>#{{ product.No }}</h3>
<p></p>
<span class="price"></span>
</div>
</div>
</a>
<div class="prod-ui">
</div>
</div>
</div>
</template>
</div>
If the query takes more than a few seconds I would implement the server side filtering, but really thats preference for you. If you go with client-side filters, you can use the built in filterBy filter:
<div v-for="product in products | filterBy category in 'Item_Disc_Group' | filterBy collection in 'Collection' | filterBy design in 'Fancy_Color_Intensity'">
Just make the default value '' instead of All so that if no filter is selected then the list won't be filtered at all.
<option value="" selected>All</option>
Then you can also use a pagination filter to further page the results (borrowed from this fiddle):
data:function(){
return {
currentPage: 0,
itemsPerPage: 1,
resultCount: 0
}
},
computed: {
totalPages: function() {
return Math.ceil(this.resultCount / this.itemsPerPage)
}
},
methods: {
setPage: function(pageNumber) {
this.currentPage = pageNumber
}
},
filters: {
paginate: function(list) {
this.resultCount = list.length
if (this.currentPage >= this.totalPages) {
this.currentPage = this.totalPages - 1
}
var index = this.currentPage * this.itemsPerPage
return list.slice(index, index + this.itemsPerPage)
}
}
That would be added last after the filtering:
<div v-for="product in products | filterBy category in 'Item_Disc_Group' | filterBy collection in 'Collection' | filterBy design in 'Fancy_Color_Intensity' | paginate">
You'd also want to add buttons to support pagination, ie:
<ul>
<li v-repeat="pageNumber: totalPages">
{{ pageNumber+1 }}
</li>
</ul>

MeteorJS the good way to build & access my documents

I'm trying to build an MeteorJS App. This is a kind of playlist manager.
It looks like spotify, There is 3 colums so I made 3 templates,
from left to right :
- The playlists list
- The medias of the selected playlist
- The selected media's details
so here's my code :
server.js
Playlists = new Meteor.Collection("playlists");
if (Meteor.isServer) {
Meteor.startup(function() {
if (Playlists.find().count() === 0) {
var names = ["test1",
"222",
"test3",
"444",
"test5",
"666"];
for (var i = 0; i < names.length; i++)
Playlists.insert({'name': names[i]});
}
return (
Meteor.methods({
addPlaylist: function(playlistName) {
Playlists.insert({'name': playlistName, 'medias': []});
},
delPlaylist: function(playlistId) {
Playlists.remove({'_id': playlistId});
},
renPlaylist: function(playlistId, newName) {
Playlists.update({'_id': playlistId}, {'$set': {'name': newName}});
},
addMedia: function(playlistId, newMedia) {
var current_playlist = Playlists.findOne({'_id': playlistId});
Playlists.update(current_playlist, {$push: {'medias': newMedia}});
}
})
);
});
Playlists.allow({
insert: function(userId, doc) {
return (false);
},
update: function(userId, doc, fields, modifier) {
return (false);
},
remove: function(userId, doc) {
return (false);
}
});
}
my templates :
<template name="t_playlistsCol">
<button id="newPlaylist" class="btn btn-primary" type="button">
New Playlist
</button>
<div id="listPlaylist">
{{#each playlists}}
<button class="playlist {{Pselected}} btn btn-default" type="button">
{{name}}
</button>
{{/each}}
</div>
</template>
<template name="t_mediasCol">
{{#if current_playlist}}
<div class="menuPlaylist">
<img id="playPlaylist" class="btn" src="icon_play1.png">
<h4>{{current_playlist}}</h4>
<div id="optionsPlaylist">
<button id="insertMedia" class="btn btn-primary">Insert</button>
<button id="renamePlaylist" class="btn btn-info">Rename</button>
<button id="deletePlaylist" class="btn btn-danger">Delete</button>
</div>
</div>
<table id="listMedias">
<thead>
<tr>
<th class="mediaName">Titre</th>
<th class="mediaType">Type</th>
<th class="mediaTime">Durée</th>
</tr>
</thead>
<tbody>
{{#each medias}}
<tr class="media {{Mselected}}">
<td class="mediaName">{{name}}</td>
<td class="mediaType">{{type}}</td>
<td class="mediaTime">{{time}}</td>
</tr>
{{/each}}
</tbody>
</table>
{{else}}
<div class="menuPlaylist">
<h3 id="noPlaylist">Select a playlist</h3>
</div>
{{/if}}
</template>
<template name="t_previewCol">
{{#if current_media}}
<div class="menuPreview">
<p>{{current_media}}</p>
</div>
{{else}}
<div class="menuPreview">
<h3 id="noPreview">Select a media</h3>
</div>
{{/if}}
</template>
client.js :
(
Playlists = new Meteor.Collection("playlists");
if (Meteor.isClient) {
Template.t_playlistsCol.playlists = function() {
return (Playlists.find({}, {sort: {"name": 1}}));
};
Template.t_playlistsCol.events = {
'click #newPlaylist': function() {
var playlistName = prompt("Nom de la playlist : ");
if (playlistName) {
Meteor.call('addPlaylist', playlistName);
}
},
'click .playlist': function() {
Session.set("selected_playlist", this._id);
}
};
Template.t_playlistsCol.Pselected = function() {
return ( Session.equals("selected_playlist", this._id) ? "Pselected" : '' );
};
Template.t_mediasCol.current_playlist = function() {
var playlist = Playlists.findOne(Session.get("selected_playlist"));
return (playlist && playlist.name);
};
Template.t_mediasCol.medias = function() {
var current_playlist = Playlists.findOne(Session.get("selected_playlist"));
return ( current_playlist.medias );
};
Template.t_mediasCol.events = {
'click #insertMedia': function() {
var playlistId = Session.get("selected_playlist");
var newMedia = {
name: "mediaTest",
type: "img",
time: "00:15"
};
newMedia._id = new Meteor.Collection.ObjectID();
Meteor.call('addMedia', playlistId, newMedia);
},
'click #deletePlaylist': function() {
var playlistId = Session.get("selected_playlist");
Meteor.call('delPlaylist', playlistId);
},
'click #renamePlaylist': function() {
var playlist = Playlists.findOne(Session.get("selected_playlist"));
var newName = prompt("Renommer " + playlist.name + " en :");
if (newName) {
Meteor.call('renPlaylist', playlist._id, newName);
}
},
'click .media': function() {
Session.set("selected_media", this._id);
}
};
Template.t_mediasCol.Mselected = function() {
return ( Session.equals("selected_media", this._id) ? "Mselected" : "" );
};
Template.t_previewCol.current_media = function() {
var playlistId = Session.get("selected_playlist");
var mediaId = Session.get("selected_media");
var playlist = Playlists.find({'_id': playlistId});
return(playlist.medias[0] && playlist.medias[0].name);
};
Accounts.ui.config({
passwordSignupFields: 'USERNAME_ONLY'
});
}
I'm a newbie, I'm learning Meteor for 3 weeks.
SO, MY PROBLEM is that, I want the user to be able to select a media and see its details with the template "t_previewCol" .
It works for the playlists, but I don't have what I want with the helper "Template.t_previewCol.current_media", it prints this error when I do a console.log to debug :
Exception in template helper:
Template.t_previewCol.current_media#http://localhost:3000/client
/client.js?7212665c7dc29cf721272fa4cabeb499f2e18bf5:69:5
bindToCurrentDataIfIsFunction/<#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:2448:7
Blaze.wrapCatchingExceptions/<#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1552:7
Spacebars.call#http://localhost:3000/packages
/spacebars.js?8717c3bee1160f47e7a46ea4e1bd0796f944cad8:169:5
#http://localhost:3000/client
/template.client.js?d2b9a924f64621cd0bcfc1292538f5b63523959a:117:5
Blaze.If/</<#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:2275:11
viewAutorun/<#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1805:7
Blaze.withCurrentView#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:2038:5
viewAutorun#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1804:5
Deps.Computation.prototype._compute#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:214:5
Deps.Computation#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:148:5
Deps.autorun#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:362:7
Blaze.View.prototype.autorun#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1803:7
Blaze.If/<#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:2277:1
fireCallbacks#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1818:9
Deps.nonreactive#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:382:5
Blaze._fireCallbacks/<#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1815:5
Blaze.withCurrentView#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:2038:5
Blaze._fireCallbacks#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1814:3
Blaze.materializeView#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1830:3
.visitObject#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1458:7
.visit#http://localhost:3000/packages
/htmljs.js?fcf2660be84fbc0c33b97ee8932dbd46612f3566:116:7
doMaterialize#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1862:13
Deps.nonreactive#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:382:5
doRender#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1860:7
viewAutorun/<#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1805:7
Blaze.withCurrentView#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:2038:5
viewAutorun#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1804:5
Deps.Computation.prototype._compute#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:214:5
Deps.Computation#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:148:5
Deps.autorun#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:362:7
Blaze.View.prototype.autorun#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1803:7
Blaze.materializeView/<#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1851:5
Deps.nonreactive#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:382:5
Blaze.materializeView#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1850:3
.visitObject#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1458:7
.visit#http://localhost:3000/packages
/htmljs.js?fcf2660be84fbc0c33b97ee8932dbd46612f3566:116:7
.visitArray#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1363:7
.visit#http://localhost:3000/packages
/htmljs.js?fcf2660be84fbc0c33b97ee8932dbd46612f3566:114:9
.visitTag#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1441:9
.visit#http://localhost:3000/packages
/htmljs.js?fcf2660be84fbc0c33b97ee8932dbd46612f3566:101:11
.visitArray#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1363:7
.visit#http://localhost:3000/packages
/htmljs.js?fcf2660be84fbc0c33b97ee8932dbd46612f3566:114:9
.visitTag#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1441:9
.visit#http://localhost:3000/packages
/htmljs.js?fcf2660be84fbc0c33b97ee8932dbd46612f3566:101:11
.visitArray#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1363:7
.visit#http://localhost:3000/packages
/htmljs.js?fcf2660be84fbc0c33b97ee8932dbd46612f3566:114:9
doMaterialize#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1862:13
Deps.nonreactive#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:382:5
doRender#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1860:7
viewAutorun/<#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1805:7
Blaze.withCurrentView#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:2038:5
viewAutorun#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1804:5
Deps.Computation.prototype._compute#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:214:5
Deps.Computation#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:148:5
Deps.autorun#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:362:7
Blaze.View.prototype.autorun#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1803:7
Blaze.materializeView/<#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1851:5
Deps.nonreactive#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:382:5
Blaze.materializeView#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1850:3
.visitObject#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1458:7
.visit#http://localhost:3000/packages
/htmljs.js?fcf2660be84fbc0c33b97ee8932dbd46612f3566:116:7
.visitArray#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1363:7
.visit#http://localhost:3000/packages
/htmljs.js?fcf2660be84fbc0c33b97ee8932dbd46612f3566:114:9
doMaterialize#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1862:13
Deps.nonreactive#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:382:5
doRender#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1860:7
viewAutorun/<#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1805:7
Blaze.withCurrentView#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:2038:5
viewAutorun#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1804:5
Deps.Computation.prototype._compute#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:214:5
Deps.Computation#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:148:5
Deps.autorun#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:362:7
Blaze.View.prototype.autorun#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1803:7
Blaze.materializeView/<#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1851:5
Deps.nonreactive#http://localhost:3000/packages
/deps.js?d9b2b2601bdab0f57291b38e7974a7190b8aac01:382:5
Blaze.materializeView#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:1850:3
Blaze.render#http://localhost:3000/packages
/blaze.js?309c2a3b573dca998c07c493ba4953d451b2c963:2068:3
instantiateBody#http://localhost:3000/packages
/templating.js?e2c0d3bbe4292a0b20c3083eaf4fcd0f5f91bb52:245:7
ready#http://localhost:3000/packages
/meteor.js?7a66be7a03504cd2c18dd47b699e6233b60675ed:641:6
Perhaps its because of way I built my documents, they look like that :
{
_id: "idP",
name: "nameP",
medias: [
{
_id: "idM1",
name: "nameM1"
},
{
_id: "idM2",
name: "nameM2"
},
...
]
}
I tried to give you a maximum of details about my problem, I hope someone could help me.
thanks.
EDIT :
I have fixed the behavior of my "preview column" when the user click on a media
Template.t_previewCol.current_media = function() {
var playlistId = Session.get("selected_playlist");
var mediaId = Session.get("selected_media");
var playlist = Playlists.findOne({'_id': playlistId});
for (var i = 0 ; i < playlist.medias.length ; ++i)
if (playlist.medias[i]._id._str === mediaId._str)
return(playlist.medias[i] && playlist.medias[i].name);
return (null);
};
I was trying to do
if (playlist.medias[i]._id === mediaId)
but since I've assigned the medias._id using Meteor.Collection.ObjectId() it was not working.
Now I just want to understand what is the error I pasted above.
Playlists.find returns a cursor. I think that you want Playlists.findOne.
Template.t_previewCol.current_media = function() {
var playlistId = Session.get("selected_playlist");
var mediaId = Session.get("selected_media");
var playlist = Playlists.findOne({'_id': playlistId});
return(playlist.medias[0] && playlist.medias[0].name);
};

How do I detect if an object has been added using angular.forEach AngularJS

I am trying to add objects to $scope.orderitems and if the object is already in the $scope.orderitems I want to change the quantity property of the object using angular.forEach instead of adding another object. Whenever I call the additem function I get an error that orderitems is not defined.
Here is my code
HTML
<input type="text" ng-model="item.name">
<button type="button" ng-click="additem(item)">
<ul>
<li ng-repeat="orderitem in orderitems">
<p>{{ orderitem.name }} | {{ orderitem.qty }}</p>
</li>
</ul>
JS
app.controller('OrderCtrl', function($scope) {
$scope.orderitems = [];
$scope.additem = function(data) {
angular.forEach(orderitems, function(orderitem) {
if (orderitem.id === data.id) {
orderitem.qty = orderitem.qty++;
} else {
data.qty = 1;
$scope.orderitems.push(data);
}
});
};
});
Here's a working fiddle: http://jsfiddle.net/rodhartzell/hbN4G/
HTML
<body ng-app="app">
<div ng-controller="OrderCtrl">
<input type="text" ng-model="item.name">
<button type="button" ng-click="additem()">add</button>
<ul>
<li ng-repeat="orderitem in orderitems">
<p>{{ orderitem.name }} | {{ orderitem.qty }}</p>
</li>
</ul>
</div>
CONTROLLER
var app = angular.module('app', []);
app.controller('OrderCtrl', function($scope) {
$scope.orderitems = [{name: 'foo', id:1, qty:1}];
$scope.additem = function() {
var exists = false;
var data = {
id : $scope.orderitems.length + 1,
name: $scope.item.name,
qty: 1
}
angular.forEach($scope.orderitems, function (item) {
if (item.name == data.name) {
exists = true;
item.qty++;
return false;
}
});
if(!exists){
$scope.orderitems.push(data);
}
};
});
$scope.orderitems = [];
$scope.additem = function(data) {
var item = null
angular.forEach(orderitems, function(orderItem) {
if (orderItem.id === data.id) {
item = orderItem
return false;
}
});
if (item == null) {
item = {
id: data.id, qty : 0
}
$scope.orderitems.push(item)
}
item.qty++
};

Categories

Resources