Angularjs adding dynamically form fields in various forms - javascript

Using ng-repeat I am creating bunch of forms with values in it. With each form there is also button to add rows to that particular form with new fields. Code is below
HTML:
<form name="{{form.name}}"
ng-repeat="form in forms">
<h2>{{form.name}}</h2>
<div ng-repeat="cont in form.contacts">
<input type="text" class="xdTextBox" ng-model="cont.ac"/>
<input type="text" class="xdTextBox" ng-model="cont.a_number"/>
<input type="text" class="xdTextBox" ng-model="cont.p_id"/>
</div>
<button ng-click="submit(form)">Submit</button>
<button ng-click="addFields(form)">Add</button>
<hr>
</form>
Javascript:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.forms = [{
"name" : "form1", "ac": 251, "a_number": "7933", "p_id": 33
}, {
"name": "form2", "ac": 252, "a_number": "7933", "p_id": 4
}, {
"name": "form3", "ac": 253, "a_number": "7362", "p_id": 3
}];
$scope.addFields = function (form) {
form.contacts.push({name:'', ac: '', a_number: '', p_id: '' });
}
$scope.submit = function(form){
console.log(form.contacts);
}
});
It is not working. Here is the plunker for it:
http://plnkr.co/edit/THdtLgkwKrV7imqZGjL2?p=preview
This is how it should be looking(Difference is data object received from db is little different than this previously asked question):
http://plnkr.co/edit/fETiSYVW7Y5C1yTCwizd?p=preview
Please let me know where the problem is. Thanks

Your addFields method is the problem. Just add a case for when form.contacts is undefined and set it to empty array. Or make each form item start with a contacts key set to an empty array.
$scope.addFields = function (form) {
if(typeof form.contacts === 'undefined') {
form.contacts = [];
}
form.contacts.push({name:'', ac: '', a_number: '', p_id: '' });
}
Works with that change in this fork of your plunk.
Angular also has a helper function for determining when something is undefined you might want to use though I do not know if it really makes any difference.
angular.isUndefined(form.contacts)

Related

Vue - submitting dynamically created form

I am creating a form dynamically with the data that I get from the backend:
{
"title": "Contact Me",
"fields": [
{
"label": "Name",
"type": "textbox",
"required": "1"
},
{
"label": "Email",
"type": "email",
"required": "1"
},
{
"label": "Message",
"type": "textarea",
"required": "1"
},
{
"label": "Submit",
"type": "submit",
"required": null
}
]
}
In Vue the component where I am making this form looks like this:
<form #submit.prevent="submit()" class="form">
<template v-for="input in ninjaForm.fields">
<div v-if="input.type != 'submit' && input.type != 'textarea'" class="control">
<input
v-bind:value="form[input.label]"
class="input is-large"
:type="input.type"
:name="input.label.toLowerCase()"
:required="input.required == 1">
<label>{{ input.label }}</label>
</div>
<div v-if="input.type == 'textarea'" class="control">
<textarea
v-bind:value="form[input.label]"
class="textarea"
:name="input.label.toLowerCase()">
</textarea>
<label>{{ input.label }}</label>
</div>
<div v-if="input.type == 'submit'">
<button class="button is-primary">{{ input.label }}</button>
</div>
</template>
</form>
I would like to submit this data back to the backend, but I am not sure how to do that, I have tried with something like this:
data() {
return {
form: {},
};
},
methods: {
submit() {
let payload = {
headers: {
'Content-Type': 'application/json'
},
params: JSON.parse(JSON.stringify(this.form))
};
console.log(payload);
this.$backend.post('submit', null, payload)
.then(_ => {
this.response = 'Meldingen ble sendt!';
}, err => {
console.warn(err);
this.response = 'En feil oppstod under innsending av skjemaet, prøv igjen senere.';
});
}
}
But when I am doing console.log(this.form) I get an observer object, and if I do console.log(payload) I get an empty params property. What am I doing wrong and how should I fix this so that I can send form data as a params object?
I have tried with setting the form properties on created method, like this:
created() {
this.ninjaForm.fields.forEach(field => this.form[field.label.toLowerCase()] = '');
},
Which has made an object with properties that looks like this:
form: {
email:"",
message:"",
name:"",
submit:""
}
But, when I was submitting the form, the values of this properties where still empty:
v-bind:value="form[input.label.toLowerCase()]"
I have also tried with changing v-bind:value to v-model, but then I have got an error:
v-model does not support dynamic input types. Use v-if branches
instead.
Please check this thread:
https://github.com/vuejs/vue/issues/3915#issuecomment-294707727
Seems like it works with v-model. However, this doesn't work when you use a v-bind on the input type. The only workaround is to create a v-if for every possible form type. Really annoying, but there seems to be no apparent other solution.

How to filter json using angular filter

Hey i have little problem with angular filter.
I import post from wordpress, and i would really like to filter them by tags, like, now show only post with tag = ENG, or show only post with tag = GER.
This is how my html looks like
<div ng-controller="ThreeMainPosts">
<div ng-repeat="threePost in threePosts | filter : {data.data.posts[0].tags[0].slug = 'ENG'} ">
<div three-post="threePost">
<h1>CONTENT</h1></div>
</div>
</div>
Controller
myModule.controller('ThreeMainPosts', function($scope, $location, WordPressNewsService) {
var postsPerPage = 3;
var orderBy = 0;
WordPressNewsService.getPosts(postsPerPage, orderBy).then(function(data) {
$scope.threePosts = data.data.posts;
});
});
and the json
{ id: 312, type: "post", slug: "la-bamba-3", url: "sada2", … }
attachments:[]
author:{ id: 1, slug: "ds", name: "hnews", first_name: "", last_name: "", … }
categories:[{ id: 6, slug: "ludzie", title: "Ludzie", description: "", parent: 0, post_count: 2 }]
tags: [{ id: 32, slug: "en", title: "EN", description: "EN", post_count: 1 }]
url:"http://xxx0.co,/?p=312"
previous_url:"http://hirsch-news.iterative.pl/?p=306"
status:"ok"
I tried make the filter in the controller but i can only do this for single element, for example:
if(data.data.posts[0].tags[0].slug == "ENG"){
$scope.threePosts = data.data.posts;
}
Any ideas guys?
Have nice day! :)
Made a quick filter, can change it up to your needs. Hope it helps. Angular $filter Docs
Here's a Codepen with angular's built in $filter.
myModule
.controller('ThreeMainPosts', function($scope, $location, WordPressNewsService, $filter) {
var postsPerPage = 3;
var orderBy = 0;
var tagToSortBy = 'EN'
WordPressNewsService.getPosts(postsPerPage, orderBy).then(function(data) {
$scope.threePosts = $filter('postFilter')(data.data.posts, tagToSortBy);
});
})
.filter('postFilter', function() {
return function(post, tag) {
if (post.tags.slug === tag) {
return post;
}
};
});
If you wanted to do this in the template it would be like this.
<div ng-controller="ThreeMainPosts">
<div ng-repeat="post in threePosts | postFilter : 'ENG' ">
<div three-post="threePost">
<h1>CONTENT</h1>
</div>
</div>
</div>
I think you want the Array.filter function, in combination with Array.some
var postsWithTagSlugENG = data.data.posts.filter(function (post) {
return post.tags.some(function (tag) {
return tag.slug == "ENG"
});
});
Here is another approach using the filter provided by Angular:
In javascript:
$filter('filter')(data.data.posts, tagToSortBy);
In HTML:
<input type="text" name="searchTag" placeholder="Filter by Any Property" ng-model="search.$" />
<input type="text" name="searchTag" placeholder="Filter by Tag" ng-model="search.tag" />
<div ng-repeat="post in threePosts | filter : search ">
The difference between this answer and #alphapilgrim is that you don't have to create your own logic to handle the filtering. Angular provides a base filter that works well in many, if not most situations.
Here are the docs if you would like to learn more about it. It is pretty powerful if you dig deep.
https://docs.angularjs.org/api/ng/filter/filter

Strange behaviour Angular driven select list

According to paper "How to set the initial selected value of a select element using Angular.JS ng-options & track by" by #Meligy which I used as a guidance to learn and solve my problem with implementing a select list (ng-options), I still encounter some strange collaterale behaviour.
Although the basic behaviour finally does what it should do, see Test Plunk, I still encounter strange behaviour on the selected item in that list. Not in my test plunk though, implemented in my developement site.
app.controller("TaskEditCtrl", function($scope) {
$scope.loadTaskEdit = loadTaskEdit;
function loadTaskEdit() {
taskLoadCompleted();
tasktypesLoadCompleted();
}
function taskLoadCompleted() {
$scope.tasks = [{
Id: 1,
Name: "Name",
Description: "Description",
TaskTypesId: 4
}
];
$scope.current_task_tasktypesid = $scope.tasks[0].TaskTypesId;
}
function tasktypesLoadCompleted() {
var tasktypes = [{ Id: 1, Name: "A" },
{ Id: 2, Name: "B" },
{ Id: 3, Name: "C" },
{ Id: 4, Name: "D" }];
$scope.available_tasktypes_models = tasktypes
}
$scope.submit = function(){
alert('Edited TaskViewModel (New Selected TaskTypeId) > Ready for Update: ' + $scope.tasks[0].TaskTypesId);
}
loadTaskEdit();
});
HTML
<form class="form-horizontal" role="form" novalidate angular-validator name="editTaskForm" angular-validator-submit="UpdateTask()">
<div ng-repeat="task in tasks">
<div>
<select ng-init="task.TaskTypes = {Id: task.TaskTypesId}"
ng-model="task.TaskTypes"
ng-change="task.TaskTypesId = task.TaskTypes.Id"
ng-options="option_tasttypes.Name for option_tasttypes in available_tasktypes_models track by option_tasttypes.Id">
</select>
</div>
</div>
<div class="">
<input type="submit" class="btn btn-primary" value="Update" ng-click="submit()" />
</div>
</form>
As said, see my test plunk which shows exactly what it supposed to do. Moreover, using 5 self-explaining images, I do hope to make my troulbe bit clearer what's the problem.
I'm a bit lost to figure out what's so troublesome. My 'water' is telling me something wrong or missing in css. Did have anybody out their ever have face comparable? What could cause me this trouble? Does have anybody out there have a clue?
Thanks in advance
[1
[]2
[]3
[]4
Apparently I'm a rookie on css. Any suggestion is welcome!
CSS
#region "style sheets"
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/css/site.css",
"~/content/css/bootstrap.css",
"~/content/css/bootstrap-theme.css",
"~/Content/css/font-awesome.css",
"~/Content/css/morris.css",
"~/Content/css/toastr.css",
"~/Content/css/jquery.fancybox.css",
"~/Content/css/loading-bar.css"));
#endregion "style sheets"
The key with the dropdown is to set the model to the object that was selected. I updated your code to behave the way that I believe you are asking for it to work.
The key differences are:
Set the ng-model of the dropdown to the selected object and not the id of the selected item. This will give you access to the full selected object and all it's properties.
Remove the ng-change binding - this is not necessary with 2 way data binding, and the value on the model (whatever is put in for ng-model) will automatically be updated.
In your HTML you were using properties that were never declared in the Controller $scope. I updated those to reflect the available variables that were in scope.
For more information on dropdowns please see the angular documentation. It's very useful for figuring these types of issues out - https://docs.angularjs.org/api/ng/directive/select
// Code goes here
var app = angular.module("myApp", []);
app.controller("TaskEditCtrl", function($scope) {
$scope.tasks = {};
$scope.current_task_tasktypesid = null;
$scope.selected_task_tasktype = null;
$scope.loadTaskEdit = loadTaskEdit;
function loadTaskEdit() {
taskLoadCompleted();
tasktypesLoadCompleted();
//EDIT: DEFAULT DROPDOWN SELECTED VALUE
$scope.selected_task_tasktype = $scope.available_tasktypes_models[2];
}
function taskLoadCompleted() {
$scope.tasks = [{
Id: 1,
Name: "Name",
Description: "Description",
TaskTypesId: 4
}
];
$scope.current_task_tasktypesid = $scope.tasks[0].TaskTypesId;
}
function tasktypesLoadCompleted() {
var tasktypes = [{ Id: 1, Name: "A" },
{ Id: 2, Name: "B" },
{ Id: 3, Name: "C" },
{ Id: 4, Name: "D" }];
$scope.available_tasktypes_models = tasktypes
}
$scope.submit = function(){
alert('submitted model: ' + $scope.selected_task_tasktype.Id);
}
loadTaskEdit();
});
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#*" data-semver="1.2.9" src="http://code.angularjs.org/1.2.9/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="myApp" ng-controller="TaskEditCtrl as edit">
<form class="form-horizontal" role="form" novalidate angular-validator name="editTaskForm" angular-validator-submit="UpdateTask()">
<div ng-repeat="task in available_tasktypes_models">
<div>Task (Id): {{task.Id}}</div>
<div>Name: {{task.Name}}</div>
<div>Descripton: {{task.Description}}</div>
</div>
<p>Current Task.TaskTypesId: {{selected_task_tasktype.Id}}</p>
<div>
<select
ng-model="selected_task_tasktype"
ng-options="option_tasttypes.Name for option_tasttypes in available_tasktypes_models track by option_tasttypes.Id">
</select>
</div>
<p>{{task.TaskTypes}}</p>
<p>{{selected_task_tasktypesid = task.TaskTypes}}</p>
<div class="">
<input type="submit" class="btn btn-primary" value="Update" ng-click="submit()" />
</div>
</form>
</body>
</html>
First, I need to state the implementation of #Meligy and the suggested input of 'dball' are correct. So, go with the flow of your choice.
Keep notice on your style sheets.
Finally, I figured out that the style property 'color' with the value 'white' of selector #editTaskWrapper as identifier of the parent
<div id="editTaskWrapper">
acted as the bad guy. One way or the other, if I comment 'color: white' in
#editTaskWrapper {
background-color: #337AB7;
/*color: white;*/
padding: 20px;
}
the selected item in the selectlist becomes visible. All other controls and values are not affected, only the selected list item.

Show different buttons matching array values

So here's my problem, i'm using AngularJS and i'm getting JSON from PHP, and displaying all my data with ng-repeat. I already have done this.
Now I want to check if some data is in "Array1" and if it is, change the correspndent data from the ng-repeat. I know it sounds really weird, but let me put an example with code:
Here's array1 values
{
"23",
"48",
"51"
}
So when i get the data, it's something like this:
{
id : "23",
name: "example"
}
And for every JSON object i'm using ng-repeat to display them all like this:
<div ng-model="data.posts" ng-repeat="post in posts | orderBy:'-' | unique: 'id'">
...
<button>This button will show if "id" matches</button>
<button>This button will show if "id" not matches</button>
</div>
I want to compare if an id of array1 matches an id from the JSON data and if it matches show one button and if not show other.
I'm on this like 2 weeks, and i can't get the problem solved, and i don't see any way to get it.
Thx for reading at least and sorry for my bad english!
Your array1 should be an array and can add a function in controller to check match id.
in controller:
$scope.array1 = ["23","48","51"];
$scope.checkInArray1 = function(id) {
var index = $scope.array1.indexOf(id);
if(index < 0){
return false;
} else {
return true;
}
};
and in your html:
<button ng-if="checkInArray1(post.id)">This button will show if "id" matches</button><br>
<button ng-if="!checkInArray1(post.id)">This button will show if "id" not matches</button>
Making the assumption that {"23","48","51"} should be a array ["23","48","51"]
You could do something like this:
Working Fiddle: http://jsfiddle.net/ravenous52/rgyom4yd/
myApp.controller('MyCtrl', ['$scope',
function($scope) {
$scope.knownIds = ["23", "48", "51"];
$scope.data = {
posts: [{
id: "23",
name: "example23"
}, {
id: "51",
name: "example51"
}, {
id: "99",
name: "example99"
}]
}
}
]);
<section ng-controller="MyCtrl">
<div ng-repeat="post in data.posts">
<button ng-show="knownIds.indexOf(post.id) >-1">This button will show if "id" matches</button>
<button ng-hide="knownIds.indexOf(post.id) >-1">This button will show if "id" not matches</button>
</div>
</section>
https://jsfiddle.net/alair016/4wc44on1/
<div ng-app='myApp' ng-controller="MyCtrl">
<div ng-model="data.posts" ng-repeat="post in data.posts">
<button ng-if="array1.indexOf(post.id) >-1">{{post.name}} id matches</button>
<button ng-if="array1.indexOf(post.id) == -1">{{post.name}} id does not match</button>
</div>
</div>
var myApp = angular.module('myApp',[])
.controller('MyCtrl', ['$scope', function($scope) {
$scope.array1 = ["23","48","51"];
$scope.data = {
posts : [
{
id : "23",
name: "example"
},
{
id: "24",
name:"second example"
}
]
};
}]);

angularjs i am using multiple select tag how to clear its all option after saved in db

How to clear multiple select option after saving into DB, i am using ng-model to clear it. Its clearing in back-end but not in UI side.
In controller I am writing:
smsType = {};
smsType.smsTypeId = [];
HTML code:
<div class="form-group">
<select ng-model="smsType.smsTypeId" ui-jq="chosen" multiple
class="w-md"
ng-options="s.id as s.name for s in smsoption.name">
</select>
</div>
Its not reflecting in ui side
Please give me some suggestion i am new to angularjs
Please see demo below
you missed $scope here
smsType.smsTypeId = [];
should be
$scope.smsType.smsTypeId = [];
// Code goes here
angular.module("myApp", []);
angular.module("myApp").controller("SelectCtrl", ["$scope",
function($scope) {
$scope.smsoption = {
name: [{
"id": "122",
"name": "denmark"
}, {
"id": "123",
"name": "france"
}, {
"id": "124",
"name": "italy"
}]
};
$scope.saveit = function() {
console.log($scope.selectCenter);
$scope.smsType.smsTypeId = [];
}
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<h1>ngOption demo</h1>
<div ng-app="myApp">
<div ng-controller="SelectCtrl">
<select ng-model="smsType.smsTypeId" ui-jq="chosen" multiple class="w-md" ng-options="s.id as s.name for s in smsoption.name">
</select>
<hr/>You have chosen:
<span ng-repeat="type in smsType.smsTypeId">{{type}} | </span>
<button ng-click="saveit()">Save</button>
</div>
</div>
The model is the output, not the input. To clear it you need to clear smsoption. The model should reflect the options you have selected, not the other way around.
smsoption = [];
Should do it

Categories