I've got a form that allows users to create a service. Currently you can only add one provider to that service.
I'd like to allow users to add up to 10 providers, using the "Add Another Provider" button.
Here's my code at the moment:
add-service.html
<form role="form" name="createServiceForm">
<input type="text" ng-model="title">
<h2>Attach Provider</h2>
<input type="text" ng-model="provider.title">
<textarea rows="3" ng-model="provider.description"></textarea>
<button type="submit">Add Another Provider</button>
<button type="submit" ng-click="createService()">Submit</button>
</form>
main.js
$scope.createService = function() {
var newService = {
title: $scope.title,
providers: {
provider: {
title: $scope.provider.title,
description: $scope.provider.description
}
},
};
var promise = ServiceService.add(newService);
};
I could duplicate parts of the code like so:
<input type="text"ng-model="provider1.title">
<input type="text"ng-model="provider2.title">
<input type="text"ng-model="provider3.title">
...
providers: {
provider1: {
title: $scope.provider1.title,
},
provider2: {
title: $scope.provider2.title,
},
provider3: {
title: $scope.provider3.title,
}
...
}
But that seems like a messy solution...
What's the best way to duplicate the provider portion of the form, when you click "Add Another Provider" without repeating it 10 times in my HTML and in my newService object?
You can accomplish what you want by using ng-repeat. I've made providers into an array, which you can then iterate over. You could use ng-repeat with an object if the key is important to you.
Also added a function which will push a new provider onto the array, which will then show in the form.
main.js
$scope.providers = [];
$scope.addProvider = function() {
$scope.providers.push({
title: '',
description: ''
});
};
// Start with one provider
$scope.addProvider();
$scope.createService = function() {
var newService = {
title: $scope.title,
providers: $scope.providers,
};
var promise = ServiceService.add(newService);
};
addService.html
<form role="form" name="createServiceForm">
<input type="text" ng-model="title">
<h2>Attach Provider</h2>
<div ng-repeat="provider in providers">
<input type="text" ng-model="provider.title">
<textarea rows="3" ng-model="provider.description"></textarea>
</div>
<button ng-click="addProvider()">Add Another Provider</button>
<button type="submit" ng-click="createService()">Submit</button>
</form>
Related
I have created a form in a modal which allows someone to enter in plan details. I have then created the scope form in ng-model attribute as you can see below...
<form>
<div class="form-group">
<label>{{plans.title}}</label>
<input type="text" name="title" ng-model="plans.title" class="form-control" placeholder="Enter Title" required />
</div>
<div class="form-group">
<label>{{plans.overview}}</label>
<textarea name="overview" ng-model="plans.overview" class="form-control" placeholder="Overview/Purpose" required />
</div>
<div class="form-group">
<label>{{plans.notes}}</label>
<textarea name="notes" ng-model="plans.notes" class="form-control" placeholder="Plan Notes" required />
</div>
<div class="form-group">
<label>{{plans.visualplan}}</label>
<div class="button" ngf-select ng-model="plans.visualplan" name="visualplan" ngf-pattern="'image/*'" ngf-accept="'image/*'" ngf-max-size="20MB" ngf-min-height="100" >Upload Visual Plan</div>
</div>
<div class="form-group">
<button type="submit" ng-click="submit()" Value="Post">Post</button>
</div>
</form>
In my code I am then trying to pull the data from the form into my scope object for plans under title, overview, notes and visualplan. Then i have coded this to upload the data from the form into my firebase json. However upon submitting the details, the upload to json process works correctly, but it is uploading the default values for title, overview, notes and visualplan which i have initiatlly set in my dailyplans.js file. What i want to upload is the details which I have attached through ng-model instead of the initial set values. Can anyone spot what I am doing wrong?
Below is my js file.
$scope.submit = function() {
$scope.plans = {
title: 'title',
overview: 'overview',
notes: 'notes',
visualplan: 'visual plan'
}
if (authData) {
ref.child('teaching-plans').child('teaching-plans' + authData.uid).set($scope.plans).then(function(authdata) {
console.log('successful');
}).catch(function(error) {
console.log(error);
});
}
}
You are resetting the plans object when user clicks on submit. Ideally it should be outside of submit method.
This is how you should do it
$scope.plans = {
title: 'title',
overview: 'overview',
notes: 'notes',
visualplan: 'visual plan'
}
$scope.submit = function(plans) {
if (authData) {
ref.child('teaching-plans').child('teaching-plans' + authData.uid).set(plans).then(function(authdata) {
console.log('successful');
}).catch(function(error) {
console.log(error);
});
}
}
And also update the html as
<div class="form-group">
<button type="submit" ng-click="submit(plans)" Value="Post">Post</button>
</div>
Hope this helps.
Just don't overwrite your plans object:
$scope.submit = function() {
$scope.plans.title = 'title';
$scope.plans.overview = 'overview';
$scope.plans.notes = 'notes';
$scope.plans.visualplan = 'visual plan;
if (authData) {
ref.child('teaching-plans').child('teaching-plans' + authData.uid).set($scope.plans).then(function(authdata) {
console.log('successful');
}).catch(function(error) {
console.log(error);
});
}
}
This way angular can fire the listeners correctly.
I am using the CRUD module in mean.js to add data to my webapp.
I am having no issues adding in strings etc, however I am having issues with embeded data.
My desired data format is below.
{
"_id":"5559abc02ef1bcdc2e6e6137",
"messages": [
"title":"title of msg",
"msg":"msg content"
],
"created":"2015-05-19T09:30:25.117Z",
"department":"finance",
"name":"accounts receivable"
}
From this snippet I want to be able to push data into the messages field. I have seen ideas on how to do this in posts such as this pushing object into array schema in Mongoose.
However I am not sure how I can implement this soloution with angular.
So far I have the below, which works for all fields except the messages field.
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
/**
* Team Schema
*/
var TeamSchema = new Schema({
name: {
type: String, //eg accounts receivable
default: '',
required: 'Please fill Team name',
trim: true
},
department: {
type: String, //eg finance
default: '',
required: 'Please fill department',
trim: true
},
messages: [
{
title: {type: String},
msg: {type: String}
}
],
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
/**
* Create a Team
*/
var mongoose = require('mongoose'),
errorHandler = require('./errors.server.controller'),
Team = mongoose.model('Team'),
_ = require('lodash');
exports.create = function(req, res) {
var team = new Team(req.body);
team.user = req.user;
team.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(team);
}
});
};
/**
* Angular controller
*/
$scope.create = function() {
// Create new Team object
var team = new Teams ({
name: this.name,
department: this.department,
messages: this.messages.title
//this.messages[0].title
});
// Redirect after save
team.$save(function(response) {
$location.path('teams/' + response._id);
// Clear form fields
$scope.name = '';
$scope.department = '';
$scope.messages.title = '';
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
Angular View
<form class="form-horizontal" data-ng-submit="create()" novalidate>
<fieldset>
<div class="form-group">
<label class="control-label" for="name">Name</label>
<div class="controls">
<input type="text" data-ng-model="name" id="name" class="form-control" placeholder="Name" required>
</div>
</div>
<div class="form-group">
<label class="control-label" for="department">Department</label>
<div class="controls">
<input type="text" data-ng-model="department" id="department" class="form-control" placeholder="Department" required>
</div>
</div>
<div class="form-group">
<label class="control-label" for="messages">messages</label>
<div class="controls">
<input type="text" data-ng-model="messages.title" id="messages" class="form-control" placeholder="messages">
</div>
</div>
<div class="form-group">
<input type="submit" class="btn btn-default">
</div>
<div data-ng-show="error" class="text-danger">
<strong data-ng-bind="error"></strong>
</div>
</fieldset>
</form>
How can I save the messages title and msg like I am saving the other items?
I would also potentially want to give users the ability to add their own fields to this messages field so they could add their own customization to the model, so it would be good if the solution rather than explicitly mentioned title and message, instead referenced each item.
You need to create an array of messages in the $scope.create function, something like this when creating the new team object:
// Create new Team object
var team = new Teams ({
name: this.name,
department: this.department,
messages: [
{ title: this.messages.title, msg: "" }
]
});
In order to add multiple messages with different titles etc, I'd create a scope variable to hold the messages (e.g. $scope.messages = [{title:"",msg:""}]) then use ng-repeat to iterate over it in your template to create multiple inputs:
<input type="text" data-ng-repeat="message in messages" data-ng-model="message.title" id="messages" class="form-control" placeholder="messages">
You could then have a button for "add message", wire up it's click to push another {title:"",msg:""} onto the $scope.messages array. Lastly, you'd then update your $scope.create function again to add that array as the value for the messages field:
// Create new Team object
var team = new Teams ({
name: this.name,
department: this.department,
messages: this.messages
});
On clearing the form, just set $scope.messages back to its initial single-item array value.
I am trying to add a "hidden" field to a basic form in Angular (using Firebase as the backend). I'm having trouble figuring out how to include this field as part of the array when the form is submitted. I want to include {type: 'Basic'} as part of the array. I've looked at the other related posts on this site, but am still unsure how to apply to my particular situation.
Any suggestions on how to do this?
Javascript:
myApp.controller('NewProjectCtrl', function ($location, Projects) {
var editProject = this;
editProject.type = 'Basic'; //this is the hidden field
editProject.save = function () {
Projects.$add(editProject.project).then(function(data) {
$location.path('/');
});
};
});
HTML:
<form>
<div class="control-group form-group">
<label>Name</label>
<input type="text" name="name" ng-model="editProject.project.name">
</div>
<label>Description</label>
<textarea name="description" class="form-control" ng-model="editProject.project.description"></textarea>
<button ng-click="editProject.save()" class="btn btn-primary">Save</button>
</form>
You don't need a hidden form field, just submit your value in your controller like this:
editProject.save = function () {
editProject.project.type = 'Basic';
Projects.$add(editProject.project).then(function(data) {
$location.path('/');
});
};
All attributes of your editProject.project will be submitted, as you may notice in the developer console.
I would structure the controller a bit different.. here is an example (I am considering you are using angular-resource, where Projects returns a Resource?):
myApp.controller('NewProjectCtrl', function ($location, Projects) {
$scope.project = new Projects({type: 'Basic'});
$scope.save = function () {
$scope.project.$save().then(function(data) {
$location.path('/');
});
};
});
<form ng-submit="save()">
<div class="control-group form-group">
<label>Name</label>
<input type="text" name="name" ng-model="project.name">
</div>
<label>Description</label>
<textarea name="description" class="form-control" ng-model="project.description"></textarea>
<input type="submit" value="Save" class="btn btn-primary" />
</form>
The save function will $save the new project resource (this is an default method and will make a POST on the given resource URL).
i have to create a form using content editor web part in SharePoint 2010. I have to hide some item or div based on group permission (example: admin,user) using angularjs.
There have two ways to solve your problem:
You receive all the data and you display it or not based on the current role, helped by a display function. jsFiddle1
Javascript code:
var demoApp = angular.module('demoApp', []);
demoApp.controller('PermissionsForm', function ($scope) {
// Mock data. You must receive it from your server
$scope.mockData = {
field1: {
value: 'field1 value',
roles: ['admin','user']
},
field2: {
value: 'field2 value',
roles: ['admin']
},
field3: {
value: 'field3 value',
roles: ['admin','user']
},
role: 'user'
};
$scope.displayField = function(fieldName){
var foundRole = false;
angular.forEach($scope.mockData[fieldName].roles, function(value, key) {
if (value == $scope.mockData.role){
foundRole = true;
}
});
return foundRole;
};
});
HTML code:
<div data-ng-app="demoApp" data-ng-controller="PermissionsForm" class="main">
<form>
<div ng-if="displayField('field1')">
<label for="field1">Field 1</label>
<input id="field1" value="{{mockData.field1.value}}">
</div>
<div ng-if="displayField('field2')">
<label for="field2">Field 2</label>
<input id="field2"value="{{mockData.field2.value}}">
</div>
<div ng-if="displayField('field3')">
<label for="field3">Field 3</label>
<input id="field3" value="{{mockData.field3.value}}">
</div>
</form>
</div>
You receive only the data related to each roles/permission and you build your interface with the list of fields. This is the more secure way to hide info. jsFiddle2
Javascript code:
var demoApp = angular.module('demoApp', []);
demoApp.controller('PermissionsForm', function ($scope) {
// Mock data. You must receive it from your server
$scope.mockData = {
field1: {
value: 'field1 value'
},
field3: {
value: 'field3 value'
},
field4: {
value: 'field4 value'
}
};
$scope.displayField = function(fieldName){
if ( $scope.mockData[fieldName] == undefined )
return false;
return true;
};
});
HTML code:
<div data-ng-app="demoApp" data-ng-controller="PermissionsForm" class="main">
<form>
<div ng-if="displayField('field1')">
<label for="field1">Field 1</label>
<input id="field1" value="{{mockData.field1.value}}">
</div>
<div ng-if="displayField('field2')">
<label for="field2">Field 2</label>
<input id="field2"value="{{mockData.field2.value}}">
</div>
<div ng-if="displayField('field3')">
<label for="field3">Field 3</label>
<input id="field3" value="{{mockData.field3.value}}">
</div>
<div ng-if="displayField('field4')">
<label for="field4">Field 4</label>
<input id="field4" value="{{mockData.field4.value}}">
</div>
</form>
</div>
From a secure point of view, the second solution is the best, because your are not exposing the data in the client side (browser)
I have this model:
var Contact = Backbone.Model.extend({
defaults: function () {
return {
idc: ""
name: ""
email: "",
phones: new Array()
}
},
urlRoot: 'admin/contact'
});
This form (underscore template):
<form>
<input type="hidden" value="{{ idc }}" />
<p>
<label>Name:</label>
<input type="text" name="name" value="{{ name}}" />
</p>
<p>
<label>Email:</label>
<input type="text" name="email" value="{{ email }}" />
</p>
<p>
<label>Phones:</label>
<input type="text" name="phones[]" value="" />
<input type="text" name="phones[]" value="" />
<input type="text" name="phones[]" value="" />
</p>
<button class="cancel">Cancel</button><button class="save">Save</button>
</form>
And when I click in save, this function into Contact View:
e.preventDefault();
var formData = {},
prev = this.model.previousAttributes();
$(e.target).closest("form").find(":input").each(function () {
var el = $(this);
formData[el.attr("name")] = el.val();
});
this.model.set(formData);
this.model.save();
this.render();
I expect that when the function is called, it creates an array to send for the PHP file with the phones, so I can store it in the database. But looking at the browser console the attribute array is with the value: []
Is there something I´m missing to pass it to the PHP file?
PS: The array is in the formData array, but when I call this.model.save() looks like it lost the array.
Anyway, Thankyou!
Your problem is basically that you're using jQuery's serializeArray. serializeArray is great if you want to create a model for every form element, because it produces JSON like this (example JSON taken from the jQuery documentation):
[
{name: 'firstname', value: 'Hello'},
{name: 'lastname', value: 'World'},
{name: 'alias'}, // this one was empty
]
However, you don't want that, you want to create a single model from the combined elements; in other words you want:
{
firstname: 'Hello',
lastname: 'World',
alias: undefined
}
There are jQuery plug-ins that produce output like that if you want, but personally I'd recommend just writing your own. If you have a form view with an onSubmit handler, you could do something like:
this.model.set('name', this.$('[name="name"]').val());
this.model.set('email', this.$('[name="email"]').val());
// etc.
that's tailored specifically for your app and serializes the data the exact way you want.