Gridstack Remove specific Elements - gridstack

I have the following:
<div class="row">
<div class="col-md-12">
<div class="trash">
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="grid-stack">
<div class="grid-stack-item" gs-h="1" gs-w="12" gs-x="0" gs-y="0" gs-locked="true" gs-no-move="false" gs-no-resize="true" gs-id="test1" data-isdefault="1" data-isremovable="-1" id="test1">
<div class="grid-stack-item-content">
Announcements
</div>
</div>
<div class="grid-stack-item" gs-h="2" gs-w="4" gs-x="0" gs-y="1" id="test2" data-default="1">
<div class="grid-stack-item-content">Tickets</div>
</div>
<div class="grid-stack-item" gs-h="2" gs-w="4" gs-x="4" gs-y="1" id="test3" data-default="1">
<div class="grid-stack-item-content">Alerts</div>
</div>
<div class="grid-stack-item" gs-h="2" gs-w="4" gs-x="8" gs-y="1" id="test4" data-default="0">
<div class="grid-stack-item-content">Emails</div>
</div>
</div>
</div>
</div>
The grid displays perfectly fine but I would like to have certain elements that the users will not be able to remove. What I tried is to check if the element has a data attribute and add it back to the grid but I lose the html id of the element. Is there a better way of doing this?
let grids = GridStack.initAll({
cellHeight: 100,
acceptWidgets: true,
dragInOptions: { revert: 'invalid', scroll: false, appendTo: 'body', helper: 'clone' },
removable: '.trash'
});
grids[0].on('added removed change', function(e, items) {
let str = '';
items.forEach(function(item) {
if (e.type=='removed' && $('#'+item.el.id).data('default')==1) {
let is_default = item.el.dataset.isdefault;
let is_removable = item.el.dataset.isremovable;
alertify.error('Cannot remove a default widget');
let wdtg = {
x: item.x,
y: item.y,
w: item.w,
h: item.h,
id: item.id,
content: item.el.firstElementChild.innerHTML
};
}
//maybe there is a way to select the newly created element to add the data- attributes back? and the ID
str += ' (x,y)=' + item.x + ',' + item.y + ' ' + item.el.id + ' '+item.w +' Extras: '+item.default+' '+item.removable;
});
});
There is another grid below but it is irrelevant to this question, that is why I am using initAll
I would like the users to be able to move the elements around but some of them should not be removable.
Thank you

So I figured out a solution that works but I am not very confident in it.
grids[0].on('added removed change', function(e, items) {
let str = '';
var wdgt;
items.forEach(function(item) {
if (e.type=='removed' && $('#'+item.el.id).data('isdefault')==1) {
let is_default = item.el.dataset.isdefault;
let is_removable = item.el.dataset.isremovable;
alertify.error('Cannot remove a default widget');
wdtg = {
x: item.x,
y: item.y,
w: item.w,
h: item.h,
id: item.id,
content: item.el.firstElementChild.innerHTML
};
grids[0].addWidget(wdtg);
//get all items
let all_items = grids[0].getGridItems();
//get length of array
let numberOfElems = all_items.length;
//add back all attributes to the last element in the array
//as it seems that gridstack pushes the new element when using
//addWidget to its array
all_items[numberOfElems-1].setAttribute('data-isdefault', $('#'+item.el.id).data('isdefault'));
all_items[numberOfElems-1].setAttribute('data-isremovable', $('#'+item.el.id).data('isremovable'));
all_items[numberOfElems-1].setAttribute('id', item.el.id);
}
str += ' (x,y)=' + item.x + ',' + item.y + ' ' + item.el.id + ' '+item.w +' Extras: '+item.default+' '+item.removable;
});
console.log(e.type + ' ' + items.length + ' items:' + str);
});

Related

filtered elements using computed: problems with paginate in VueJS

I'm using Laravel and VueJs,
I'm trying the following: I 've created a search bar to find users by their names, last name or email.
I used computed to write my filter but I've realized that my filter only filters over the 10 first elements (because I'm using paginate to show all users stored in my database)
...what can I do to make my filter works over all my users instead each ten that gives me paginate (if it's possible keeping paginate, please)?
This is my script and template (thank you very much):
<script>
import UpdateProfile from './users/UpdateProfile';
import CreateUser from './users/CreateUser';
import User from '../models/user';
export default {
components: {UpdateProfile, CreateUser},
data() {
return {
showUpdateModal: false,
showCreateModal: false,
users: [],
user: new User(),
search:'',
paginator: {
current: 1,
total: 1,
limit: 10,
}
}
},
mounted() {
this.goToPage(1);
},
methods: {
userPermissions(user) {
return this.CONSTANTS.getUserType(user.permissions);
},
addUser(user) {
this.showCreateModal = false;
this.api.post('/users', user).then(() => {
this.goToPage(this.paginator.current);
});
},
editUser(user) {
this.user = JSON.parse(JSON.stringify(user));
this.showUpdateModal = true;
},
updateUser(user) {
this.showUpdateModal = false;
this.api.put('/users/' + user.id, user).then(() => {
this.goToPage(this.paginator.current)
});
},
deleteUser(user) {
this.api.delete('/users/' + user.id).then(() => {
this.goToPage(this.paginator.current)
});
},
navigatePrev(page) {
this.goToPage(page)
},
navigateNext(page) {
this.goToPage(page)
},
goToPage(page) {
this.api.get('/users?page=' + page + '&limit=' + this.paginator.limit).then(response => {
this.users = response.data;
this.paginator = response.paginator;
});
}
},
computed:{
filteredUsers: function () {
return this.users.filter((user) => {
var searchByName = user.name.toLowerCase().match(this.search.toLowerCase());
var searchByLastName = user.lastname.toLowerCase().match(this.search.toLowerCase());
var searchByEmail = user.email.toLowerCase().match(this.search.toLowerCase());
if(searchByName){
return searchByName;
}
if(searchByLastName){
return searchByLastName;
}
if(searchByEmail){
return searchByEmail;
}
});
}
}
}
</script>
<template>
<div class="container">
<div class="button is-primary" #click="showCreateModal=true" v-if="CONSTANTS.hasRootPermissions()">
<span class="icon"><i class="fas fa-plus fa-lg"></i></span>
<span>Add User</span>
</div>
<br><br>
<create-user v-if="CONSTANTS.hasRootPermissions()"
:show="showCreateModal"
v-on:save="addUser"
v-on:close="showCreateModal=false"/>
<!--Search Users-->
<div class="control is-expanded">
<h1>Search users</h1>
<input class="input" type="text" v-model="search" placeholder="Find a user"/>
</div>
<br><br>
<!--Search Users-->
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Admin</th>
<th>Permissions</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="user in filteredUsers">
<td>{{user.name}}</td>
<td>{{user.lastname}}</td>
<td>{{user.email}}</td>
<td>{{user.isAdmin ? 'yes' : 'no'}}</td>
<td>{{userPermissions(user)}}</td>
<td>
<div class="button is-info" #click="editUser(user)">
<span class="icon"><i class="far fa-edit"></i></span>
<span>Edit</span>
</div>
</td>
<td>
<div class="button is-danger" #click="deleteUser(user)">
<span class="icon"><i class="far fa-trash-alt"></i></span>
<span>Delete</span>
</div>
</td>
</tr>
</tbody>
</table>
<paginator :paginator="paginator" v-on:prev="navigatePrev" v-on:next="navigateNext"/>
<update-profile :data="user" :show="showUpdateModal" v-on:save="updateUser" v-on:close="showUpdateModal=false"/>
</div>
</template>
You can get all your users (if that's not too much data) at start and then paginate them on a clientside.
Something like:
mounted() {
this.api.get('/users').then(response => {
this.users = response.data;
this.paginator.total = Math.ceil(this.users.length / this.paginator.limit);
});
},
methods: {
goToPage(page) {
this.paginator.current = page;
}
},
computed:{
filteredUsers: function () {
return this.users.filter((user) => {
var searchByName = user.name.toLowerCase().match(this.search.toLowerCase());
var searchByLastName = user.lastname.toLowerCase().match(this.search.toLowerCase());
var searchByEmail = user.email.toLowerCase().match(this.search.toLowerCase());
if(searchByName){
return searchByName;
}
if(searchByLastName){
return searchByLastName;
}
if(searchByEmail){
return searchByEmail;
}
}).filter((el, index) => {
return ( index >= (this.paginator.current - 1) * this.paginator.limit
&& index < this.paginator.current * this.paginator.limit);
});
}
}
}
Update
Other option would be to perform serching on a serverside and to send a search string with every page request:
methods: {
goToPage(page) {
this.api.get('/users?page=' + page + '&limit=' + this.paginator.limit
+ '&search=' + this.search).then(response => {
this.users = response.data;
this.paginator = response.paginator;
});
},
performSearch() {
this.goToPage(1);
},
},
}
with search block in a template:
<!--Search Users-->
<div class="control is-expanded">
<h1>Search users</h1>
<input class="input" type="text"
v-model="search" placeholder="Find a user"
#change="performSearch"/>
</div>
You can add debouncing to get results after you type or add a "search!" button after your search input field to trigger performSearch().
<!--Search Users-->
<div class="control is-expanded">
<h1>Search users</h1>
<input class="input" type="text"
v-model="search" placeholder="Find a user"/>
<button #click="performSearch">Search!</button>
</div>

Node.js with express insert new field into existing mongoDB document from server side

Hello I am looking to implement a way to dynamically insert new fields to an existing mongoDB document from the server side with node.js and express.
For example in the local mongoDB the document looks like this.
{
value: 'Google',
url: 'https://google.com',
env: 'Test'
}
I have a route that will already update the current document fields from a form on the UI. However I want to combine that logic with the ability to insert new fields upon updating.
The route below handles updating the document with the existing fields.
router.put("/:id", (req, res) => {
let value = req.body.value;
Application.findByIdAndUpdate(req.params.id, req.body.application, (err,
updatedApp) => {
if(err){
console.log(err);
} else {
console.log(updatedApp)
req.flash("info", updatedApp.value + " " + "successfully edited!");
res.redirect("/qa-hub/applicationmanager");
}
});
});
On the front end I use EJS with a form to update the document. Example below:
<div class="row">
<div class="col-md-6">
<div class="form-group">
<input class="form-control" type="url" name="application[url]" value="<%= application.url %>" required>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<select class="form-control" name="application[env]" required="true">
<option class="text-center" value='<%= application.env %>'><%= application.env %></option>
<option value='Beta'>Beta</option>
<option value='Dev'>Dev</option>
<option value='Does Not Apply'>Does Not Apply</option>
<option value='Prod'>Prod</option>
<option value='QA'>QA</option>
<option value="Test">Test</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<a class="btn btn-outline-warning" href="/qa-hub/applicationmanager">Cancel</a>
</div>
<div class="form-group">
<button class="btn btn-outline-primary" id="btn" >Update</button>
However i'd like to add three additional fields upon submitting the form. I want to capture the currently logged in user that performed the edit and the date and time. I already have that worked out but how could I implement inserting new data to the existing document from the route.put while also keeping the logic to update the current fields if any changes are made.
So after the user makes some changes and updates the three fields the document would look something like below, except id handle the logic to get the currently logged in user at that time and the date/time and pass it in but for the example below I will hardcode it.:
{
value: 'Google',
url: 'https://google.com',
env: 'Test',
updatedBy: "Test User"
timeUpdated: "12:54",
dateUpdated: "7/25/2018"
}
So ultimately I want to keep a log of the changes and than be able to add it to the UI.
So with a little help from this post TypeError: callback.apply is not a function (Node.js & Mongodb) I was able to append new fields to the existing document using $set. However when trying to perform the req.body.application before $set it would throw an error stating that callback.apply is not a function. So I just created a callback if you will to update the document after setting the new fields. I know its messy but just wanted to get it working feel free to use and clean up the code for your self.
router.put("/:id", (req, res) => {
let value = req.body.value;
let value = req.body.value;
let date = new Date();
let hour = date.getHours();
hour = (hour < 10 ? "0" : "") + hour;
let min = date.getMinutes();
min = (min < 10 ? "0" : "") + min;
let time = hour+":"+min;
let year = date.getFullYear();
let month = date.getMonth() + 1;
month = (month < 10 ? "0" : "") + month;
let day = date.getDate();
day = (day < 10 ? "0" : "") + day;
today = month+"/"+day+"/"+year;
let updatedTo = month+"/"+day+"/"+year;
let updatedT = hour+":"+min;
let updatedBy = req.user.username;
//Find the document based on it's ID and than append these three new fields
Application.findByIdAndUpdate(req.params.id,
{ $set: {
updatedTime: `${updatedT}`,
updatedToday: `${updatedTo}`,
updatedBy: `${updatedBy}`
}}, { upsert: true },
(err,updatedApp) => {
if(err){
return handleError(err);
} else {
// Than if any changes were made from the UI we apply those updates taken
// from the form with req.body.application
Application.findByIdAndUpdate(req.params.id, req.body.application,
(err, updatedApp) => {
if(err){
return handleError(err);
} else {
console.log(updatedApp)
req.flash("info", updatedApp.value + " " + "successfully edited!");
res.redirect("/qa-hub/applicationmanager");
}
}
});
});

Server side pagination with limited number of requests

My front-end is Angular5. Back-end is REST API NODE.JS and the database is POSTGRES.
Table named organization in my postgres contain 100k ( 100 000) rows.
I have table that contains list of all organizations with information such as name of the organization,location etc.
At this moment my frontend only displays 50 organization. I have console logged this and my backend is only sending array of 50.
My goal is to display all organizations( 100 000 of them) in the frontend table using server-side pagination.
Pagination is already made for the current values that are displayed and thats 50 of them. Code is below
Frontend table below that works ( currently displaying only 50 organization sent from backend)
<div class="card-body">
<div class="row">
<div class="table-col">
<div class="card table">
<div class="row header">
<div class="col col-md-6">Name</div>
<div class="col col-md-2">ID</div>
<div class="col col-md-2">Location</div>
<div class="col col-md-2">Person in charge</div>
</div>
<div *ngFor="let group of organizations">
<div *ngIf="group.name == 'all'">
<div class="row content-row" *ngFor="let organization of group.array | search: term | orderBy: order | paginate: {itemsPerPage: 13, currentPage:page1, id: '1'}"
[routerLink]="['/organization/edit', organization.id]">
<div class="col col-md-6">{{organization.name}}</div>
<div class="col col-md-2">{{organization.id}}</div>
<div class="col col-md-2" *ngIf="organization.place?.fullName != null">{{organization.place?.fullName}}</div>
<div class="col col-md-2" *ngIf="organization.place?.fullName == null"><span class="badge badge-danger">-- N/A -- </span></div>
<div *ngIf="organization.person?.fullname != null" class="col col-md-2">{{organization.person?.fullname}}
</div>
<div *ngIf="organization.person?.fullname == null" class="col col-md-2"><span class="badge badge-danger">-- N/A -- </span></div>
</div>
</div>
<div *ngIf="group.name != 'all'">
<div class="row content-row">
<div class="col col-md-12 group-name" (click)="toggleGroup(group.name)">{{group.name + ':'}}</div>
</div>
<div *ngIf="showGroup == group.name">
<div class="row content-row" *ngFor="let organization of group.array | search: term | paginate: {itemsPerPage: 5, currentPage:page2, id: '2'}"
[routerLink]="['/organization/edit', organization.id]">
<div class="col col-md-6" style="padding-left:23px;">{{organization.name}}</div>
<div class="col col-md-2">{{organization.id}}</div>
<div class="col col-md-2">{{organization.place?.fullName}}</div>
<div class="col col-md-2">{{organization.person?.fullname}}
</div>
</div>
</div>
</div>
</div>
<div *ngIf="!(organizations[0].array.length > 0)" class="row noResults">
<label>No results..</label>
</div>
<div *ngIf="organizations[0].name == 'all'" class="paggination-row">
<div class="paggination">
<pagination-controls (pageChange)="page1 = $event" id="1" maxSize="5" directionLinks="true" autoHide="true" previousLabel="Previous"
nextLabel="Next">
</pagination-controls>
</div>
</div>
<div *ngIf="organizations[0].name != 'all' && showGroup != ''" class="paggination-row">
<div class="paggination">
<pagination-controls (pageChange)="page2 = $event" id="2" maxSize="5" directionLinks="true" autoHide="true" previousLabel="Previous"
nextLabel="Next">
</pagination-controls>
</div>
</div>
</div>
</div>
</div>
</div>
Now on backend in my config I have the following code:
"host": "0.0.0.0",
"port": 3030,
"public": "../public/",
"paginate": {
"default": 50,
"max": 50
},
Note: host ip changed on purpose.
Paginate is the reason why my front is only receiving 50 values when there is 100 000 of them.
Now if I go on about and change default and max value to 100k my frontend should show all organizations but will probably crash the client and the server in process of doing this.
If i do paginate false that won't be much of a help either.
Now I am wondering how can I keep having limited requests like 50 or 100(so my server is alive) but still show all organizations in my front-end using server side pagination or whatever necessary.
Any help is appreciated and thank you so much for taking your time to read this.
edit1: service to load all organizations:
import { Injectable } from '#angular/core';
import { Http, Headers } from "#angular/http";
import 'rxjs/add/operator/map';
import { AppSettings } from '../../../../../../app.settings';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
//service made to comunicate with backend
#Injectable()
export class CreateOrganizacijeService {
private dataSource = new BehaviorSubject<any>("default")
currentData = this.dataSource.asObservable();
constructor(
private http: Http
) { }
updateData(data) {
this.dataSource.next(data);
}
getAll() {
let headers = new Headers();
let token = localStorage.getItem('feathers-jwt');
headers.append('Content-Type', 'application/json');
headers.append('Authorization', 'Bearer ' + token)
return this.http.get(AppSettings.API_ENDPOINT + '/organization', { headers: headers }).map(res => res.json())
}
getOne(id) {
let headers = new Headers();
let token = localStorage.getItem('feathers-jwt');
headers.append('Content-Type', 'application/json');
headers.append('Authorization', 'Bearer ' + token)
return this.http.get(AppSettings.API_ENDPOINT + '/organization?id=' + id, { headers: headers }).map(res => res.json())
}
createNew(organization) {
let headers = new Headers();
let token = localStorage.getItem('feathers-jwt');
headers.append('Content-Type', 'application/json');
headers.append('Authorization', 'Bearer ' + token)
return this.http.post(AppSettings.API_ENDPOINT + '/organization', organization, { headers: headers }).map(res => res.json())
}
delete(id) {
let headers = new Headers();
let token = localStorage.getItem('feathers-jwt');
headers.append('Content-Type', 'application/json');
headers.append('Authorization', 'Bearer ' + token)
return this.http.delete(AppSettings.API_ENDPOINT + '/organization?id=' + id, { headers: headers }).map(res => res.json())
}
edit(id, organization) {
let headers = new Headers();
let token = localStorage.getItem('feathers-jwt');
headers.append('Content-Type', 'application/json');
headers.append('Authorization', 'Bearer ' + token)
return this.http.patch(AppSettings.API_ENDPOINT + '/organization?id=' + id, organization, { headers: headers }).map(res => res.json())
}
}
component ngonit ( where I load organizations)
ngOnInit() {
this.currentUser = JSON.parse(localStorage.getItem('user'));
if(this.currentUser.roleId == '2') {
this.isAdmin = true; //check if user is admin
}
if(JSON.parse(localStorage.getItem('user')).roleId == '2') {
this.isAdmin = true; //check if user is admin
}
this.organizacijeService.currentData.subscribe(res => {
this.loadOrgs();
})
}
loadOrgs() {
this.organizacijeService.getAll().subscribe(res => {
this.organizations[0].array = res.data;
console.log(this.organizations[0])
}, err => {
this.toast.error('Organization: ' + JSON.parse(err._body).message, 'Failed')
})
}
You can load subsequent pages by increasing the $skip query parameter in increments of 50 until the page.total - 50.
I would keep in mind that showing 100k records at once will probably still lead to performance problems on the frontend.
You can use a proxy service on the server side that has pagination disabled:
app.use('organizations-unpaginated', {
find(params){
const _params = Object.assign({}, params, { paginate: false });
return app.service('organizations').find(_params);
}
})
As Daff said, you will run into performance issues and I'd generally say that rendering 100k DOM elements (almost all of which are invisible anyway) is bad practice.

Pagination meteor publish does not return records

I definitely know that something is wrong with this snippet but can't figure out the right way to get it done. I want to paginate the page where students are displayed. If I put it plainly like this return SchoolStudents.find();, it works perfectly by returning all the students but this defeats the main purpose of pagination. I'm either not sure where the problem is, either in the publish function or the helper function. What I want to achieve is that the records in SchoolStudents colleciton should be paginated to display 2 records on a page.
This is the autorun
Session.setDefault('skip', 0);
Template.view.onCreated(function () {
Session.setPersistent('ReceivedSlug', FlowRouter.getParam('myslug'));
this.autorun(function () {
Meteor.subscribe('SchoolStudents', Session.get('skip'));
});
});
this is the helper method
students(){
let myslug = trimInput(Session.get('ReceivedSlug'));
if (myslug) {
let mySchoolDoc = SchoolDb.findOne({slug: myslug});
if (mySchoolDoc) {
let arrayModuleSchool = StudentSchool.find({schoolId: mySchoolDoc._id});
if (arrayModuleSchool) {
var arrayStudentIds = [];
arrayModuleSchool.forEach(function(studentSchool){
arrayStudentIds.push(studentSchool.studentId);
});
let subReadiness = SchoolStudents.find({_id: {$in: arrayStudentIds}}).fetch();
if (subReadiness) {
return subReadiness;
}
}
}
}
}
This is the publish method
Meteor.publish('SchoolStudents', function (skipCount) {
check(skipCount, Number);
user = Meteor.users.findOne({_id:this.userId})
if(user) {
if(user.emails[0].verified) {
return SchoolStudents.find({userId: this.userId}, {limit: 2, skip: skipCount});
} else {
throw new Meteor.Error('Not authorized');
return false;
}
}
});
Blaze template
<section class="tab-section" id="content4">
{{#each student in students}}
<div class="row" style="margin-top: -20px;">
<!-- Begin Listing: 609 W GRAVERS LN-->
<div class="brdr bgc-fff pad-10 box-shad btm-mrg-20 property-listing card-1">
<div class="media">
<div class="media-body fnt-smaller">
<h4 class="media-heading">{{student.firstname}} {{student.lastname}}</h4>
<p class="hidden-xs" style="margin-bottom: 5px; margin-top: -10px;">{{trimString student.useremail 0 110}}</p><span class="fnt-smaller fnt-lighter fnt-arial">{{course.createdAt}}</span>
</div>
</div>
</div><!-- End Listing-->
</div>
{{/each}}
<ul class="pager">
<li class="studentprevious">Previous </li>
<li class="studentnext">Next </li>
</ul>
</section>
the pagination event
'click .studentprevious': function () {
if (Session.get('skip') > 0 ) {
Session.set('skip', Session.get('skip') - 2 );
}
},
'click .studentnext': function () {
Session.set('skip', Session.get('skip') + 2 );
}

Geddy - create new item

I am an absolute beginner in node.js and geddy. I've followed a few tutorials and now I try to write something similar for my purposes.
When I try to create a new item, though, I get the following message:
/arithmetic_problem_types/function%20(id)%20%7B%20%20%20%20%20%20options.id%20=%20id;%20%20%20%20%20%20return%20helpersBase.urlFor.action(options);%20%20%20%20%7D not found.
I have no idea where this could come from. I've looked through the code and found nothing.
Controller:
var ArithmeticProblemTypes = function () {
this.respondsWith =[ 'html', 'json', 'xml', 'js', 'txt'];
this.index = function (req, resp, params) {
var self = this;
geddy.model.ArithmeticProblemType.all(function (err, arithmetic_problem_types) {
self.respond({
params: params, arithmetic_problem_types: arithmetic_problem_types
});
});
};
this.add = function (req, resp, params) {
this.respond({
params: params
});
};
this.create = function (req, resp, params) {
var self = this, arithmetic_problem_type = geddy.model.ArithmeticProblemType.create({
name: '1', title: 'open', numberType: '1', numberRanges: '1', operators: '1', askedFor: '1', specialProblemCategory: '1', askedForNumDenomOrBoth: '1',
reducedFractions:'1', mixedFractions: '1'
});
arithmetic_problem_type.save(function (err, data) {
if (err) {
params.errors = err;
self.transfer('add');
} else {
self.redirect({
controller: self.name
});
}
});
};
....................................................................
};
exports.ArithmeticProblemTypes = ArithmeticProblemTypes;
add.html.ejs
<div class="hero-unit">
<%= partial('_form', {params: params}); %>
</div>
index.html.ejs
<div class="hero-unit">
<h2>Arithmetic Problem Types List</h2>
<%- linkTo('Create a new Aritmetic Problem Type', addArithmeticProblemTypePath, {class: 'btn pull-right'}) %>
</div>
<% if (arithmetic_problem_types && arithmetic_problem_types.length) { %>
<% for (var i in arithmetic_problem_types) { %>
<div class="row todo-item">
<div class="span8">
<h3><%- linkTo(arithmetic_problem_types[i].title, arithmeticProblemTypePath(arithmetic_problem_types[i].id)) %></h3>
</div>
<div class="span4"><h3><i class="icon-list-alt"></i><%= arithmetic_problem_types[i].status; %></h3></div>
</div>
<% } %>
<% } %>
How can I get rid of that message and make it work?
EDIT:
This is the beginning of the _form.html.ejs file:
<%
var isUpdate = params.action == 'edit'
, formTitle = isUpdate ? 'Update this Arithmetic Problem Type' : 'Create a new Arithmetic Problem Type'
, action = isUpdate ? arithmeticProblemTypePath(params.id) + '?_method=PUT' : arithmeticProblemTypePath
, deleteAction = isUpdate ? arithmeticProblemTypePath(params.id) + '?_method=DELETE' : ''
, btnText = isUpdate ? 'Update' : 'Add'
, nameValue = isUpdate ? arithmeticProblemTypePath.name : ''
, errors = params.errors;
%>
<form id="arithmetic-problem-type-form" class="form-horizontal" action="<%= action %>" method="POST">
....
</form>
EDIT2:
Inspecting the page where I should write the name of the item and click the add button, I've found this
<div class="hero-unit">
<form id="arithmetic-problem-type-form" class="form-horizontal" action="function (id) {
options.id = id;
return helpersBase.urlFor.action(options);
}" method="POST">
<fieldset>
<legend>Create a new Arithmetic Problem Type</legend>
<div class="control-group">
<label for="title" class="control-label">Title</label>
<div class="controls">
<input class="span6" name="name" placeholder="enter name" type="text">
</div>
</div>
<div class="form-actions">
<input class="btn btn-primary" type="submit" value="Add">
</div>
</fieldset>
</form>
</div>
Indeed the message comes from the action attribute of the form element, but how can I solve it?
The message is telling you that the requested URL could not be found. AKA 404
/arithmetic_problem_types/function%20(id)%20%7B%20%20%20%20%20%20options.id%20=%20id;%20%20%20%20%20%20return%20helpersBase.urlFor.action(options);%20%20%20%20%7D
is definitely not a nice looking url. So i'm assuming there's something wrong with your form's action attribute. If that's what happened when you validate the form.
If that's what happened when you click the link to "Create a new arithmetic problem type" then you should probably put parenthesis after addArithmeticProblemTypePath

Resources