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>
Related
Hey guys I'm really new at sails.js and I'm using version 1.0 of it. I just tried to create a CRUD application on adding article to my list and showing them. All goes right but when I want to delete or edit it says 404 error. I am going through this tutorial series and as I know this series is using sails js version 0.12.
I am using mongodb as my database as a default. Data insertion is going well but problem is when I wanted to edit or delete it. Here I think the problem is getting the id value from the url. I skipped the edit portion here and posted the delete portion here.
api/controllers/ ArticleController.js
module.exports = {
delete: function(req, res){
Articles.destroy({id:req.params.id}).exec(function(err){
if(err){
res.send(500,'Database Error');
}
res.redirect('/articles/list');
});
return false;
}
};
api/models/ Articles.js
module.exports = {
attributes: {
title:{
type:'string'
},
body:{
type:'string'
}
},
};
views/pages list.ejs
<h1 class="display-4">Articles</h1>
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Title</th>
<th></th>
</tr>
</thead>
<tbody>
<% articles.forEach(function(article){ %>
<tr>
<td><%= article.id %></td>
<td><%= article.title %></td>
<td>
<form class="d-inline" action="/articles/delete/<%= article.id %>" method="POST">
<input type="submit" class="btn btn-danger" value="Delete">
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
config/route.js
module.exports.routes = {
'/': {
view: 'pages/homepage'
},
};
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>
I'm using ngTable with this code:
HTML:
<table data-ng-table="tableParams" class="table table-condensed table-bordered table-striped">
<tbody>
<tr data-ng-repeat="task in $data">
<td data-title="''">
<input type="checkbox" style="display: block; margin: auto;" ng-model="task.IsSelected" ng-change="optionToggled()">
</td>
<td data-title="''" style="text-align: center">
<i class="glyphicon glyphicon-flag" ng-show="task.IsToday"></i>
<i class="glyphicon glyphicon-ok" ng-show="task.IsCompleted"></i>
</td>
<td data-title="'Subject'" data-sortable="'Subject'">{{task.Subject}}</td>
<td data-title="'Priority'" data-sortable="'PriorityValue'">{{task.PriorityValue}}</td>
<td data-title="'Status'" data-sortable="'StatusValue'">{{task.StatusValue}}</td>
<td data-title="'Due Date'" data-sortable="'DueDate'">{{task.DueDate}}</td>
<td data-title="'Completed'" data-sortable="'CompletedValue'">{{task.CompletedValue}}</td>
<td data-title="'Date Completed'" data-sortable="'DateCompleted'">{{task.DateCompleted}}</td>
<td data-title="'Action'">
<button type="button" style="display: block; margin: auto;" class="btn btn-info btn-xs" ng-click="editRow(task)">
<i class="glyphicon glyphicon-edit"></i>
</button>
</td>
</tr>
</tbody>
</table>
Javascript:
$scope.tableData = [];
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: { DueDate: "asc" } // initial sort order,
},
{
paginationMaxBlocks: 10,
paginationMinBlocks: 2,
getData: function($defer, params) {
var sorting = params.sorting();
var keySorting = Object.keys(sorting)[0];
var valueSorting = sorting[keySorting];
var count = params.count();
var pageIndex = params.page() - 1;
var keySearch = angular.isDefined($scope.textSearch) ? $scope.textSearch : '';
taskService.pagingTasks(pageIndex * count, count, keySearch, keySorting, valueSorting).then(function(data) {
var obj = angular.fromJson(data);
params.total(obj.Total);
formatToDateTime(obj.Data);
$scope.tableData = obj.Data;
$defer.resolve(obj.Data);
});
}
});
But when I run my website I see ngTable generate
And my browser console show this error:
I have no idea why ngTable can't generate columns header.
Currently, I must create columns header by manually.
I found my answer:
You can fix this issues base on this post :
AngularJS: 'Template for directive must have exactly one root element' when using 'th' tag in directive template
Modified these lines in file "ng-table.js" and remove tr tag in : "filterRow.html", "groupRow.html", "sorterRow.html".
(template)
$templateCache.put('ng-table/header.html', '<tr ng-if="params.hasGroup()" ng-show="$groupRow.show" class="ng-table-group-header" ng-table-group-row></tr> <tr class="ng-table-sort-header headerrow" ng-table-sorter-row></tr> <tr ng-show="show_filter" class="ng-table-filters" ng-table-filter-row></tr> ');
(directive)
function ngTableGroupRow(){
var directive = {
restrict: 'A',
//replace: true,
templateUrl: 'ng-table/groupRow.html',
scope: true,
controller: 'ngTableGroupRowController',
controllerAs: 'dctrl'
};
return directive;
}
function ngTableSorterRow(){
var directive = {
restrict: 'A',
//replace: true,
templateUrl: 'ng-table/sorterRow.html',
scope: true,
controller: 'ngTableSorterRowController'
};
return directive;
}
function ngTableFilterRow(){
var directive = {
restrict: 'A',
//replace: true,
templateUrl: 'ng-table/filterRow.html',
scope: true,
controller: 'ngTableFilterRowController'
};
return directive;
}
In this plunker I have an ngTable that is supposed to show two rows, instead it shows only the header. What's wrong with this code?
Javascript
var app = angular.module('app', ['ngTable']);
app.controller('myCtl', function($scope,$timeout,NgTableParams) {
$timeout(function() {
$scope.data = [
{ uid: 'User 1', nm: 'Name 1', ugr: 'Group 1'},
{ uid: 'User 2', nm: 'Name 2', ugr: 'Group 2'}
];
$scope.tableParams = new NgTableParams({dataset: $scope.data});
}, 1000);
$scope.toggleFilter = function (){
$scope.showFilter = !$scope.showFilter;
};
});
HTML
<div ng-controller="myCtl" ng-app="app">
Toggle Filter
<table ng-table="tableParams" show-filter="showFilter" class="table table-bordered">
<tbody>
<tr ng-repeat="u in $data">
<td title="'User ID'" filter="{ uid: 'text' }" sortable="'uid'" style="width:150px">{{ u.uid }}</td>
<td title="'Name'" filter="{ nm: 'text' }" sortable="'nm'" style="width:150px">{{ u.nm }}</td>
<td title="'Group'" filter="{ ugr: 'text'}" sortable="'ugr'" style="width:200px">{{ u.ugr }}</td>
</tr>
</tbody>
</table>
</div>
Correct Answer:
My apologies, I was too hasty in my first answer. My solution fixed it, but it was incorrect.
The real issue is that you need to change 'dataset' to 'data' in the controller, like this (using NgTable v.0.8.3):
$scope.tableParams = new NgTableParams({count: 5}, {data: $scope.data});
I have also added a count, otherwise, it displays one item at a time.
Plunkr: http://plnkr.co/edit/plDiFc4CCmrIf5YOeD5M?p=preview
UPDATE: This answer is incorrect, please see the answer marked as "correct".
It works if you change '$data' to 'data' in the HTML.
<table ng-table="tableParams" show-filter="showFilter" class="table table-bordered">
<tbody>
<tr ng-repeat="u in data">
<td title="'User ID'" filter="{ uid: 'text' }" sortable="'uid'" style="width:150px">{{ u.uid }}</td>
<td title="'Name'" filter="{ nm: 'text' }" sortable="'nm'" style="width:150px">{{ u.nm }}</td>
<td title="'Group'" filter="{ ugr: 'number'}" sortable="'ugr'" style="width:200px">{{ u.ugr }}</td>
</tr>
</tbody>
</table>
See here: http://plnkr.co/edit/WlPVGYjSshLkwbJ78xNO?p=preview
The examples on the NgTable website use v1.0.0-beta.9, so my guess is they are slightly outdated perhaps.
I have applied bindings to the following view model
var groupDeleteViewModel = {
group: { Id: ko.observable(), Name: ko.observable(), Members: ko.observableArray() },
load: function (item) {
debugger
},
remove: function (item) {
groupDeleteViewModel.group.Id(item.Id());
groupDeleteViewModel.group.Name(item.Name());
groupDeleteViewModel.group.Members(item.Members());
$("#groupDelete").show();
},
cancel: function () {
$("#groupDelete").hide();
}
}
the remove function loads the view with the data that has been passed in item to the remove function.
<div id="groupDelete" class="pop-window filter-view">
<h2>
Delete Group
</h2>
<table>
<tr>
<th>
Name
</th>
<td>
<span data-bind="text:group.Name" />
</td>
</tr>
<!--ko foreach: group.Members-->
<tr>
<th>
</th>
<td>
<div data-bind="text:Name" class="grey-border">
</div>
</td>
<td>
</td>
</tr>
<!--/ko-->
</table>
<span class="centeralign">
<input type="button" value="Delete" data-bind="click: remove" class="delete" />
<input type="button" value="Cancel" data-bind="click: cancel" />
</span>
</div>
I don't want to keep mapping each element of item to each element of groupDeleteViewmodel.group. I have done it at a lot of other places also in the code which has made the code really messy. I want to use the ko.mapping plugin to do the same thing.
Till now what I have tried is -
remove:function (item){
var data = ko.mapping.toJS(item);
ko.mapping.fromJS(data, groupDeleteViewModel.group);
$("#groupDelete").show();
}
But this just does not work. i really don't know why. It should have worked ideally.
Can someone tell what is the right way of using ko.mapping in such a case?
Thanks.
The mapping plugin is looking for mapping data already present in groupDeleteViewModel.group, but it doesn't find it, because you didn't initialize groupDeleteViewModel.group using the mapping plugin.
So instead of initializing group like you did:
group: { Id: ko.observable(), Name: ko.observable(), Members: ko.observableArray() }
initialize it using the mapping plugin:
group: ko.mapping.fromJS({ Id: undefined, Name: undefined, Members: [] })
And this is me fiddling around with your code: fiddle