Error in filter function for VueJs - filtering

I want to filter the following in VueJs 2.
My Component is the following:
<template>
Search <input name="query" v-model="query" class="form-control">
<table class="table">
<thead>
<tr>
<th>User name</th>
<th>User email/th>
<th>Get logs</th>
</tr>
</thead>
<tbody v-for="user in filteredUsers">
<tr>
<td> {{ user.firstname }} </td>
<td> {{ user.lastname }} </td>
<td> <a v-on:click="getUserLogs(user.user_id)">Show</a> </td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import ConnectionService from '../../components/services/ConnectionService';
const connectionService = new ConnectionService();
export default {
data() {
return {
users: [],
query: '',
betweenDates: {
from: '',
to: ''
},
logs: {},
logsVisibility: false
}
},
created() {
this.getUsers();
},
computed: {
filteredUsers() {
return this.findBy(this.users, this.query, 'lastname')
}
},
methods: {
getUsers() {
this.$http.get(hostname + 'name=person_list&session_id=' + sessionApiId).then(response => {
this.users = connectionService.renderMultipleInstances(response.body);
}, response => {
// error callback
});
},
getUserLogs(id) {
let self = this;
axios.post('/logs/get_user_logs', {
userId: id,
}).then(function (response) {
self.logs = response.data;
self.logsVisibility = true;
console.log(response.data);
});
},
findBy(list, value, column) {
return list.filter(function (item) {
return item[column].includes(value)
})
}
}
}
</script>
I have the following data to filter through it:
users:Array[4095]
0:Object
firstname:"Анастасия"
id:206
lastname:"Никифорова"
middlename:"Юрьевна"
user_id:192
1:Object
firstname:null
id:3362
lastname:null
middlename:null
user_id:2046
...
And error is the following:
[Vue warn]: Error in render function: "TypeError: Cannot read property 'includes' of null"

In 1:Object lastname:null. It causes your error
You can add line before return
item[column] || (item[column] = '');
or
return list.filter(function (item) {
return (item[column] || '').includes(value)
})

I had a similar problem to fix it I replace every null value from my object with a ' ' (empty string)

Related

Edit form prop values not filled in the form vuejs (reusing same form component )

I have a vuejs project, where I have my parent component as ProductGroup.vue which has a child ProductGroupmodal.vue. The productGroup has list of records, upon clicking edit button on each row the modal (ProductGroupmodal.vue) should pop up with the input fields filled with the data. I have passed each row data as prop to the child component on clicking edit button. Then, I have assigned the prop data to the form object in the created() method of child component. But the form is not filled with previous records. Here is my code below:
This is Parent component.
<template>
<div class="tables-basic">
<h2 class="page-title">Product Group - <span class="fw-semi-bold">List</span></h2>
<b-button v-b-modal.modal1 #click.prevent="newModal()">Add New</b-button>
<b-row>
<b-col>
<div class="table-resposive">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th class="hidden-sm-down">Action</th>
</tr>
</thead>
<tbody>
<tr v-for="row in allData" :key="row.id">
<td>{{row.name}}</td>
<td>
<b-button v-b-modal.modal1 #click.prevent="editModal(row)">Edit</b-button>
</td>
</tr>
</tbody>
</table>
</div>
</b-col>
</b-row>
<ProductGroupModal :editValue="editValue" :editing='editing'
/>
</div>
</template>
<script>
import ProductGroupModal from '#/components/ProductGroup/ProductGroupModal.vue';
export default {
name: 'ProductGroup',
components: { ProductGroupModal },
data() {
return {
editValue:{},
editing: false,
allData:{},
};
},
methods: {
loadData() {
ProductGroupDataService.getAll()
.then(response => {
this.allData = response.data;
})
.catch(e => {
console.log(e);
});
},
newModal(){
this.editing=false;
},
editModal(row){
this.editValue = row;
this.editing = true;
},
},
mounted() {
this.loadData();
}
};
</script>
This is my Child component (ProductGroupModal.vue):
<template>
<b-modal ref="productGroupModal" id="modal1" centered v-bind:title="this.editing==true ? 'Update' : 'Add' "
#hidden="resetModal"
#ok.prevent="submitForm() ">
<v-form ref="productGroupForm" id="productGroupForm">
<v-text-field
v-model="form.name"
label="Name"
required
></v-text-field>
</v-form>
</b-modal>
</template>
<script>
import ProductGroupDataService from "#/services/ProductGroupDataService";
export default {
props: {
editValue: {
type: Object,
default: () => ({empty: true}),
},
editing: {
type: Boolean,
default: () => ({}),
}
},
name: 'productGroupModal',
data() {
return {
form: {
id: '',
name: '',
code: '',
},
};
},
methods:{
submitForm() {
var data = {
"name": this.form.name,
"code": this.form.code
};
},
created(){
if (!this.editValue.empty) {
this.form = this.editValue
console.log('edit:'+ this.editValue);
}
else{
console.log('falseedit:'+ this.editValue);
}
}
}
</script>
I think my b-modal(child component) is rendered before the data in the form is being set through prop .How can I solve it?Can anyone help me with this please!
I can't get enough info about your b-modal components.
but I think this maybe related to the props passed to child is async.
when created, the asyncprops editValue is not ready yet. so nothing is assigned to the form.
you can add v-if on the child component, render the child component only when data is ready:
<ProductGroupModal v-if="allData.length" :editValue="editValue" :editing='editing'
/>
do not write this.form = this.editValue in created hook;
computed: {
form() {
return this.editValue || {};
}
}

Update single field using EF

I need to update a single field 'status' using EF..
View:
#model IEnumerable<DemoUserMeetings.Models.Meeting>
#{
ViewBag.Title = "Index";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<table class="table">
<tr>
<th>#Html.DisplayNameFor(m => m.MeetingFromId)</th>
<th>#Html.DisplayNameFor(m => m.MeetingToId)</th>
<th>#Html.DisplayNameFor(m => m.MeetingStartTime)</th>
<th>#Html.DisplayNameFor(m => m.MeetingEndTime)</th>
<th>#Html.DisplayNameFor(m => m.MeetingStatus)</th>
<th>#Html.DisplayNameFor(m => m.MeetingDescription)</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.MeetingFromId)</td>
<td>#Html.DisplayFor(modelItem => item.MeetingToId)</td>
<td>#Html.DisplayFor(modelItem => item.MeetingStartTime)</td>
<td>#Html.DisplayFor(modelItem => item.MeetingEndTime)</td>
<td>#Html.DisplayFor(modelItem => item.MeetingStatus)</td>
<td>#Html.DisplayFor(modelItem => item.MeetingDescription)</td>
<td>
<input type="button" class="btn btn-default btnAccept" value="Delete" id="#item.MeetingId" />
</td>
</tr>
}
Logout
<script type="text/javascript">
$('.btnAccept').click(function () {
var update_id = $(this).attr('id');
var isTrue = confirm("Accept meeting invite?");
if (isTrue) {
$.ajax({
url: '#Url.Action("AcceptMeeting","Home")',
type: 'POST',
data: { id: update_id },
success: function () {
alert('success');
},
error: function () {
alert('failed');
return false;
}
});
} else {
return false;
}
});
</script>
Controller:
[HttpPost]
public ActionResult AcceptMeeting(int id)
{
// Here i need to set status ="Accept" for particular id
return View();
}
that is what i tried, i want to update status of meeting having id to "Accepted". I know it is not a big thing but i am new to EF. i got the id of meeting in controller but dont know further process. any ideas?
try this
using (var db = new YourDBContext())
{
var meeting= context.Meeting.Find(id);
meeting.MeetingStatus = true;
db.Meeting.Attach(meeting);
db.SaveChanges();
}

How can I re-render the page after post request with react/redux?

There is a short time between the posting and the response from the server. How is it possible to cause your component to re-render when you get your positive response? I tried componentWillGetProps(){} and if-statements like
if(this.props.incomingItems){return: this.props.incomingItems}
but it none of them worked out. How did you solve this problem?
PS I'm using redux and axios for the requests.
import React, { Component } from 'react';
import { reduxForm } from 'redux-form';
import * as actions from '../../actions';
class eventView extends Component {
componentWillMount() {
this.props.eventView(this.props.params.eventID);
}
createNewRole(roleName){
this.props.createNewRole(roleName, this.props.params.eventID);
};
renderUsers(){
return this.props.eventDetails.userList.map((user)=>{
return(
<li className='list-group-item eventUserList' background-color="#f2f2f2" key={user._id}>
{user.userName}
</li>
);
});
};
deleteListItem(key){
const newKey = key.dispatchMarker.substr(44, 24);
this.props.RemoveRoleFromList(newKey)
this.props.fetchEvents();
}
renderRoles(){
return this.props.eventDetails.role.map((role)=>{
return(
<li className='list-group-item roleList' key={role._id}>
{role.roleName}
<img className="deleteListItem"
src="/img/trash.png"
key={role._id}
onClick={this.deleteListItem.bind(this)}/>
</li>
);
});
};
render() {
const { handleSubmit, fields: {eventName,location, eventPassword, roleName} } = this.props;
if(this.props.roleList){
console.log(this.props.roleList)
}
if (this.props.eventDetails){
return (
<div className='container-fluid'>
<div className="roleBox">
<form onSubmit={handleSubmit(this.createNewRole.bind(this))}>
<div>
<input {...roleName}
className="form-control roleBoxInputBar"
autoComplete="off"/>
<button className="RoleButton">Save</button>
</div>
<div className="listOfRoles">
<ul className="listOfRoles pre-scrollable">
{this.renderRoles()}
</ul>
</div>
</form>
</div>
<div>
<div>
<h1 className="eventName">
{this.props.eventDetails.eventName}
</h1>
</div>
<br/>
<table>
<tbody>
<tr>
<td className="eventViewTableLocation">Location:</td>
<td className="eventViewTable">{this.props.eventDetails.location}</td>
</tr>
<tr>
<td className="eventViewTableLocation">Date:</td>
<td className="eventViewTable">12/Feb/2018</td>
</tr>
<tr>
<td className="eventViewTableLocation">Time Left:</td>
<td className="eventViewTable">2 Days 2 Hours</td>
</tr>
</tbody>
</table>
</div>
<div className='eventViewUserBox'>
<h4 className="listOfUsers">Organisers:</h4>
<ul>
{this.renderUsers()}
</ul>
</div>
</div>
);
}else {
return (
<div>
</div>
);
}
}
}
function mapStateToProps(state) {
return { eventDetails: state.api.eventDetails };
return { roleList: state.api.roleList };
return { createdRole: state.api.createdRole };
}
export default reduxForm({
form: 'eventView',
fields: ['eventName', 'location', 'eventPassword', 'roleName']
}, mapStateToProps, actions)(eventView);
And my axios post goes something like this
export function createNewRole({roleName}, eventID){
return function(dispatch) {
axios.post(`${ROOT_URL}createRole/`+eventID, {roleName})
.then(response => {
if (response.data){
dispatch({
type: CREATED_ROLE,
payload: response.data,
});
};
})
.catch(response => dispatch(authError(response.data.error)));
};
};
Reducer:
export default function(state = {}, action) {
switch(action.type) {
case FETCH_ROLES:
return { ...state, roleList: action.payload };
case CREATED_ROLE:
return { ...state, createdRole: action.payload };
}
return state;
}
Thanks a lot!
function mapStateToProps(state) {
return { eventDetails: state.api.eventDetails };
return { roleList: state.api.roleList };
return { createdRole: state.api.createdRole };
}
This function always returns the first object. It should be:
function mapStateToProps(state) {
return {
eventDetails: state.api.eventDetails,
roleList: state.api.roleList,
createdRole: state.api.createdRole
};
}
I'm guessing roleList and createdRole are always undefined? Also it would be good if you would show the reducer.

Update form in meteor using autoform

I have a collection that handles default values for forms. I need to build a UI to update the default values themselves, instead of force updating via mongo backed.
I've used aldeed's update-each functionality. The data is being fetched from the DB and displayed in the table. However, when I try to update by inputting new values in the textbox, it does not persist. In fact, it keeps throwing this error which i'm not aware of.
Exception in template helper: TypeError: Cannot read property 'namedContext' of undefined
at Object.autoFormFieldIsInvalid
As a sample, here is what I'm working with:
Mongo Collection:
meteor:PRIMARY> db.testCollection.find()
{ "_id" : ObjectId("577ccd87f57f43d790c3ec49"), "schemaName" : "test_schema", "label" : "test_lable", "value" : "test_value" }
Schema:
test_schema = new SimpleSchema({
"schemaName": {
type: String,
},
"label": {
type: String,
},
"value": {
type: String,
}
});
testCollection.attachSchema(test_schema);
Template:
<template name = "testTemplate">
<table class="table table-bordered table-condensed">
<thead>
<tr>
<td style="width: 85px">Schema Name</td>
<td style="width: 85px">Label</td>
<td>Default Value</td>
<td style="width: 250px">New Default Value</td>
</tr>
</thead>
<tbody>
{{#each items}}
<tr>
<td>{{this.schemaName}}</td>
<td>{{this.label}}</td>
<td>{{this.value}}</td>
<td>
{{#autoForm id=updateDefaiultsID type="update" collection=testCollection doc=this autosave=true}}
{{> afFormGroup name="value" label=false}}
{{/autoForm}}
</td>
</tr>
{{/each}}
</tbody>
</table>
</template>
Helper
import { Template } from 'meteor/templating';
import '../templates/testTemplate.html';
if (Meteor.isServer) {
Meteor.publish(null, function () {
return testCollection.find();
});
testCollection.allow({
update: function () {
return true;
}
});
}
else if (Meteor.isClient) {
Template["testTemplate"].helpers({
items: function () {
return testCollection.find({}, {sort: {name: 1}});
},
updateDefaiultsID: function () {
return "testTemplate" + this._id;
}
});
}
Change this
from
<td>{{this.schemaName}}</td>
to
<td>{{this.schema_name}}</td>

Refresh datatable on Ajax success

I am using datatables and jquery dialog. Overall I have 3 forms and 3 datatables.
My script is working great but the thing I am struggling with is updating the correct datatable on success of ajax save (It doesn't even have to be the correct corresponding table, it could update all 3 tables on any of the 3 form saves.)
Any guidance would be greatly appreciated.
Page with buttons for showing datatable/forms in dialog
<div style="float:left;">
<button class="menubutton" id="view_academic">Academic</button>
<button class="menubutton" id="view_business">Business/Suppport</button>
<button class="menubutton" id="line_managers">Managers/Divisions</button>
<br/>
<br/>
</div>
<div style="float:right;">
Add Managers/Divisions
Add Academic
Add Business/Suppport
<br/>
<br/>
</div>
<div style="clear:both"></div>
<div id="academic_list">
<h2>Academic Entitlements</h2>
<table class="dataTable" id="academic_table" cellpadding="2" cellspacing="2" width="100%">
<thead>
<tr>
<th>Year</th>
<th>Employee</th>
<th>Division</th>
<th>Contract</th>
<th>Entitlement</th>
<th>Line Manager</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="4" class="dataTables_empty">Loading data from server</td>
</tr>
</tbody>
</table>
</div>
<div id="business_list" class="the_options" style="display:none;">
<h2>Business & Manual Entitlements</h2>
<table class="dataTable" id="business_table" cellpadding="2" cellspacing="2" width="100%">
<thead>
<tr>
<th>Year</th>
<th>Employee</th>
<th>FT/PT</th>
<th>Weekly Hours</th>
<th>Division</th>
<th>Commencement</th>
<th>Entitlement</th>
<th>Line Manager</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="4" class="dataTables_empty">Loading data from server</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="line_managers_list" class="the_options" style="display:none;">
<h2>Line Managers & Divisions</h2>
<table class="dataTable" id="line_managers_table" cellpadding="2" cellspacing="2" width="100%">
<thead>
<tr>
<th>Division</th>
<th>Name</th>
<th>Line Manager</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="4" class="dataTables_empty">Loading data from server</td>
</tr>
</tbody>
</table>
</div>
initialise Datatables
$(function() {
// Implements the dataTables plugin on the HTML table
var $acTable= $("#academic_table").dataTable( {
"oLanguage": {
"sSearch": "Filter:"
},
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "scripts/academic_serverside.php",
"iDisplayLength": 10,
"bJQueryUI": false,
"sPaginationType": "scrolling",
"sDom": '<"top"iflp<"clear">>rt>',
"sScrollX": "100%",
"sScrollXInner": "100%",
"bScrollCollapse": true
});
});
$(function() {
// Implements the dataTables plugin on the HTML table
var $buTable= $("#business_table").dataTable( {
"oLanguage": {
"sSearch": "Filter:"
},
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "scripts/business_serverside.php",
"iDisplayLength": 10,
"bJQueryUI": false,
"sPaginationType": "scrolling",
"sDom": '<"top"iflp<"clear">>rt>',
"sScrollX": "100%",
"sScrollXInner": "100%",
"bScrollCollapse": true
});
});
$(function() {
// Implements the dataTables plugin on the HTML table
var $lmTable= $("#line_managers_table").dataTable( {
"oLanguage": {
"sSearch": "Filter:"
},
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "scripts/line_managers_serverside.php",
"iDisplayLength": 10,
"bJQueryUI": false,
"sPaginationType": "scrolling",
"sDom": '<"top"iflp<"clear">>rt>'
});
});
$(document).ready(function() {
$(".the_options").hide();
});
Dialogs/datatables show/hide/open/close and AJAX save form:
$(document).ready(dialogForms);
function dialogForms() {
$('a.menubutton').click(function() {
var a = $(this);
$.get(a.attr('href'),function(resp){
var dialog = $('<div>').attr('id','formDialog').html($(resp).find('form:first').parent('div').html());
$('body').append(dialog);
dialog.find(':submit').hide();
dialog.dialog({
title: a.attr('title') ? a.attr('title') : '',
modal: true,
buttons: {
'Save': function() {
submitFormWithAjax($(this).find('form'));
$(this).dialog('close');
$lmTable.fnDraw('');
},
'Cancel': function() {$(this).dialog('close');}
},
close: function() {$(this).remove();},
width: 600,
height: 500
});
}, 'html');
return false;
});
}
function submitFormWithAjax(form) {
form = $(form);
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: (form.attr('method')),
dataType: 'script',
success: function(data){
$(this).dialog('close');
$lmTable.fnDraw('');
}
});
return false;
}
$(function() {
$("#add_academic")
.button()
.click(function() {
$("#academic-form").dialog( "open" );
});
$("#add_line_managers")
.button()
.click(function() {
$("#line-managers-form").dialog( "open" );
});
$("#add_business")
.button()
.click(function() {
$("#business-form").dialog( "open" );
});
$("#view_academic")
.button()
.click(function() {
$('#academic_list').show();
$('#business_list').hide();
$('#line_managers_list').hide();
});
$("#view_business")
.button()
.click(function() {
$('#academic_list').hide();
$('#business_list').show();
$('#line_managers_list').hide();
});
$("#line_managers")
.button()
.click(function() {
$('#academic_list').hide();
$('#business_list').hide();
$('#line_managers_list').show();
});
});
To update a table simply call fnDraw() on it. Since you are not using global variables, you must retrieve the table first
var $lmTable = $("#line_managers_table").dataTable( { bRetrieve : true } );
$lmTable.fnDraw();
EDIT - to show only the right table you could do something like:
function dialogForms() {
$('a.menubutton').click(function() {
var id = this.id;// Save the id of the clicked button
var a = $(this);
$.get(a.attr('href'),function(resp){
var dialog = $('<div>').attr('id','formDialog').html($(resp).find('form:first').parent('div').html());
$('body').append(dialog);
dialog.find(':submit').hide();
dialog.dialog({
title: a.attr('title') ? a.attr('title') : '',
modal: true,
buttons: {
'Save': function() {
submitFormWithAjax($(this).find('form'), id);// Pass the id to the function
function submitFormWithAjax(form, id) {
form = $(form);
var table_id;
// Choose the table to display depending on the id, i made some guesses but adjust this
switch(id){
case 'view_academic': table_id = '#academic_table';
break;
case 'view_business': table_id = '#business_table';
break;
case 'line_managers': table_id = '#line_managers_list';
break;
}
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: (form.attr('method')),
dataType: 'script',
success: function(data){
$(this).dialog('close');
// Refresh table
var oTableToUpdate = $(table_id).dataTable( { bRetrieve : true } );
$oTableToUpdate .fnDraw();
// Hide all tables
$('table').hide();
// Show the refreshed
$(table_id).show();
}
});
return false;
}