Update form in meteor using autoform - mongodb

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>

Related

Error:error Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays

I am trying to bind some JSON data from my API to HTML and iterate it over it using *ngFor in angular 4. Unfortunately, I'm getting the error in this question's title.
The code in question:
countryList.ts
export interface CountryList {
UserName : string,
Country : string[],
}
Service.ts
export class LoginServicesService {
constructor(private o:Http) { }
functionCountriesList(userName:string)
{
return this.o.get('http://localhost:55760/api/Login/GetCountries/'+userName).map((res:Response) =><CountryList[]>res.json());
}
}
Component.ts
export class LoginComponent implements OnInit {
constructor(private loginService: LoginServicesService) { }
ngOnInit() {
}
countries: CountryList[];
countryValue: number;
countryName: string;
GenerateCountries(userName: string) {
this.loginService.functionCountriesList(userName).subscribe((data) => this.countries = data);
console.log(this.countries);
}
}
Component.HTML
<table align="center">
<tr>
<td><label id="lblUserName">UserName:</label></td>
<td><input #userName type="Textbox" id="txtUserName" (keyup.enter)="GenerateCountries(userName.value)" (blur)="GenerateCountries(userName.value)" /></td>
</tr>
<tr>
<td>
<label id="lblPassword">Password:</label>
</td>
<td><input type="password" id="txtPassword"/></td>
</tr>
<tr>
<td>Domain:</td>
<td>
<select id= "district" style="width:100%" (change)="selectdrop($event)">
<option value="NIL">Select Domain</option>
<option *ngFor="let c of countries;let i=index">{{c}}</option>
</select>
</td>
</tr>
</table>
JSON from api is
{
"UserName": "hello",
"Country": [
"South Africa",
"Russia",
"India",
"America",
]
}
Your problem is that you're trying to directly iterate through the result of your API call, which a JSON object as you've pasted. You need to sub-select the "Country" field from your API response first and iterate through that.

Unable to show new properties in User schema

I'm working within a MEAN app, and I'm modifying the User module. I modified the User Schema to contain 2 new properties: casetype and Steps. casetype is just a string, and Steps is an array. I created a view to show these along with a controller. Neither are shown on the page when I run the server. If I try to show any of the preexisting properties of the logged in user, they work fine, it just seems to be the new stuff I added that doesn't work. What's more puzzling is that they save just fine to the database, and when using Mongo shell I can find the user by querying based on casetype.
view:
<div class="row">
<h1 ng-bind="vm.user.casetype"></h1>
</div>
<div class="row">
<div class="col-md-6">
<div class="tableWrapper">
<table id = "table_id" class="table table-hover">
<thead>
<tr>
<th>Step</th>
<th>Todo</th>
<th>Completed?</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="step in vm.user.steps.type | filter: query" >
<td>{{step.num}}</td>
<td>{{step.text}}</td>
<td class = "y_n">{{step.completed}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
UserSchema additions:
//case type
casetype: {
type: String,
default: 'Default Case Type'
},
//steps for case tracking
steps: {
type: [{
num: {
type: Number,
//default: 0
},
text: {
type: String,
trim: true,
//default: 'Todo for step'
},
completed: {
type: Boolean,
//default: false
}
}],
default: [{
num: 0,
text: 'todo for step',
completed: false
}]
},
Steps is an object. you need to render steps.type which is an array:
<tbody>
<tr ng-repeat="t in vm.user.steps.type | filter: query" >
<td>{{t.num}}</td>
<td>{{t.text}}</td>
<td class = "y_n">{{t.completed}}</td>
</tr>
</tbody>

Error in filter function for VueJs

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)

Not able to bind click event in kendo mvvm row template

I have kendo grid with a button to remove the current item and for that grid I have a row template. Here is my HTML:
<div class="form-horizontal">
<table class="fixed-table-width"
data-role="grid"
data-bind="source: data"
data-scrollable="false"
data-row-template="row-template">
<thead>
<tr>
<th>Item</th>
<th></th>
</tr>
</thead>
</table>
</div>
<script type="text/x-kendo-tmpl" id="row-template">
<tr>
<td><span data-bind="text: item"></span></td>
<td><button class="link" data-bind="click: remove"><i class="icon-trash"></i> Remove</button></br ></td>
</tr>
</script>
And that is my model:
function AddItemComponent($scope) {
if ($scope === null || $scope === undefined) throw new Error("Unknown scope, please provide the scope");
var self = this;
self.itemModel = {
item: "Item to Remove",
remove: function(i) {
self.viewModel.items = self.viewModel.items.splice(i);
}
};
self.viewModel = kendo.observable({
items: []
});
self.viewModel.items.push(self.itemModel);
};
But when I open the modal with this HTML, I get the following error:
kendo.binder.min.js?cdv=40:25 Uncaught TypeError: t.get is not a function(…)
If I remove the data-bind from the click event, there is no error and it just works fine, so what is wrong?
What you are trying to achieve is better done with a commands column
http://docs.telerik.com/kendo-ui/api/javascript/ui/grid#configuration-columns.command
data-columns="[{ field: 'item' }, { command: 'destroy' }]"
You don't neeed a row template anymore.
If you don't want to do this, try to wrap your itemModel in an observable, as get() is a method from kendo.data.ObservableObject
self.itemModel = kendo.observable({
item: "Item to Remove",
remove: function(i) {
self.viewModel.items = self.viewModel.items.splice(i);
}
});

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;
}