Binding ng-repeat and ng-model from controller - angularjs

I'm new to AngularJS. I'm trying to build a form with ng-repeat and having trouble wrapping my head around the angular stuff.
This is my angular controller:
// Create the 'products' controller
angular.module('products').controller('ProductsController', ['$scope', '$routeParams', '$location', 'Authentication', 'Products',
function($scope, $routeParams, $location, Authentication, Products) {
// Expose the Authentication service
$scope.authentication = Authentication;
$scope.productProperty = {
productTitle: {slug: 'productTitle', label: 'Product Title', value: '', placeholder: 'Product Title'},
productCode: {slug: 'productCode', label: 'Product Code', value: '', placeholder: 'Product Code'},
productModel: {slug: 'productModel', label: 'Product Model', value: '', placeholder: 'Product Model'},
productColor: {slug: 'productColor', label: 'Product Color', value: '', placeholder: 'Product Color'}
};
// Create a new controller method for creating new products
$scope.create = function() {
// Use the form fields to create a new product $resource object
var product = new Products({
productTitle: this.productTitle,
productCode: this.productCode,
productModel: this.productModel,
productColor: this.productColor
});
// Use the product '$save' method to send an appropriate POST request
product.$save(function(response) {
// If an product was created successfully, redirect the user to the product's page
$location.path('products/' + response._id);
}, function(errorResponse) {
// Otherwise, present the user with the error message
$scope.error = errorResponse.data.message;
});
};
}
]);
HTML:
<!-- The create product view -->
<section data-ng-controller="ProductsController">
<h1>New Product</h1>
<!-- The new product form -->
<form data-ng-submit="create()" novalidate>
<div class="row" data-ng-repeat="(keyAssets, valueAssets) in productProperty">
<div>
<label for="{{productProperty[keyAssets]['slug']}}">{{productProperty[keyAssets]['label']}}</label>
<div>
<input type="text" data-ng-model="productProperty[keyAssets]['slug']" id="{{productProperty[keyAssets]['slug']}}" placeholder="{{productProperty[keyAssets]['placeholder']}}" required>
</div>
</div>
</div>
<div>
<input type="submit">
</div>
<!-- The error message element -->
<div data-ng-show="error">
<strong data-ng-bind="error"></strong>
</div>
</form>
</section>
I'm trying to get the 'data-ng-model' set to something unique in each instance of the data-ng-repeat. But I'm not getting the desired output.
I want something like the following output:
<!-- The create product view -->
<section data-ng-controller="ProductsController">
<h1>New Product</h1>
<!-- The new product form -->
<form data-ng-submit="create()" novalidate>
<div>
<label for="productTitle">Product Title</label>
<div>
<input type="text" data-ng-model="productTitle" id="productTitle" placeholder="Product Name" required>
</div>
</div>
<div>
<label for="productCode">Product Code</label>
<div>
<input type="text" data-ng-model="productCode" id="productCode" placeholder="Product Code" required>
</div>
</div>
<div>
<label for="productModel">Product Model</label>
<div>
<input type="text" data-ng-model="productModel" id="productModel" placeholder="Product Model" required>
</div>
</div>
<div>
<label for="productColor">Product Color</label>
<div>
<input type="text" data-ng-model="productColor" id="productColor" placeholder="Product Color" required>
</div>
</div>
<div>
<input type="submit">
</div>
<!-- The error message element -->
<div data-ng-show="error">
<strong data-ng-bind="error"></strong>
</div>
</form>
How can I get the 'data-ng-model' set to something unique in each instance of the ng-repeat?

Related

Angular ngDialog not Displaying model data in $scope

Continually having issues with ng-dialog properly displaying model data. My app uses two ng-dialog instances, one to add data (in this case for a League) and a second dialog to edit data. Both use the the same ng-model data. When add League is selected, the first dialog pops up, the user populates the fields, and saves the record, the dialog is closed and the main page displays the created League along with its data. An EDIT button is presented.
The issue in this case occurs when the EDIT button is pressed.
The controller's openEditLeague method is called, which prepopulates the leagueForm with the data for the league I am trying to edit.
'use strict';
angular.module('ma-app')
.filter('trustUrl', function ($sce) {
return function(url) {
return $sce.trustAsResourceUrl(url);
};
})
.controller('HomeController', ['$scope', 'ngDialog', 'authService', 'coreDataService', 'userService', '$rootScope', 'clubService', 'schedulingService', function($scope, ngDialog, authService, coreDataService, userService, $rootScope, clubService, schedulingService) {
....
$scope.leagueForm = {
name: '',
shortname: '',
minAgeGroup: null,
maxAgeGroup: null,
type: null,
rescheduleDays: '',
consequence: '',
fine: '',
logoURL: '',
leagueId: ''
};
....
$scope.openEditLeague = function(league) {
console.log("\n\nOpening dialog to edit league");
console.log(league);
$scope.leagueForm = {
name: league.name,
shortname: league.short_name,
minAgeGroup: league.min_age_group,
maxAgeGroup: league.max_age_group,
type: league.type,
rescheduleDays: league.reschedule_time,
consequence: league.reschedule_consequence,
fine: league.reschedule_fine,
logoURL: league.logo_url
};
console.log("Current entries include: ");
console.log($scope.leagueForm);
ngDialog.open({ template: 'views/editLeague.html', scope: $scope, className: 'ngdialog-theme-default custom-width-600', controller:"HomeController" });
};
....
}])
;
I am logging the contents of the $scope.leagueForm prior to opening the ng-dialog, and the data contents are correct.
When the dialog opens however, all fields are empty.
This should be fairly straight forward data-binding, so I must be doing something wrong.
Here are the contents of the editLeague.html that are used to generate the ng-dialog:
<div class="ngdialog-message">
<div>
<h3>Edit League</h3>
</div>
<div> </div>
<div>
<form class="form-horizontal" ng-submit="editLeague()">
<div class="form-group">
<label class="sr-only" for="name">League Name</label>
<div class="col-xs-12 col-sm-6">
<input type="text" class="form-control" id="name" placeholder="league name" ng-model="leagueForm.name">
</div>
<label class="sr-only" for="shortname">League Abbreviation</label>
<div class="col-xs-12 col-sm-6">
<input type="text" class="form-control" id="shortname" placeholder="league abbreviation" ng-model="leagueForm.shortname">
</div>
</div>
<div class="form-group">
<label class="sr-only" for="minage">Minimum Age Group</label>
<div class="col-xs-12 col-sm-6">
<div class="input-group">
<div class="input-group-addon">Min Age Group</div>
<select id="minage" class="form-control" ng-model="leagueForm.minAgeGroup" ng-options="ageGroup as ageGroup.name for ageGroup in ageGroups"></select>
</div>
</div>
<label class="sr-only" for="maxage">Maximum Age Group</label>
<div class="col-xs-12 col-sm-6">
<div class="input-group">
<div class="input-group-addon">Max Age Group</div>
<select id="maxage" class="form-control" ng-model="leagueForm.maxAgeGroup" ng-options="ageGroup as ageGroup.name for ageGroup in ageGroups"></select>
</div>
</div>
</div>
<div class="form-group">
<label class="sr-only" for="type">League Type</label>
<div class="col-xs-12 col-sm-6">
<div class="input-group">
<div class="input-group-addon">Type</div>
<select id="type" class="form-control" ng-model="leagueForm.type" ng-options="leagueType as leagueType.name for leagueType in leagueTypes"></select>
</div>
</div>
<label class="sr-only" for="days">Day to Reschedule</label>
<div class="col-xs-12 col-sm-6">
<div class="input-group">
<input type="text" class="form-control" id="days" placeholder="days to reschedule" ng-model="leagueForm.rescheduleDays">
<div class="input-group-addon">Days</div>
</div>
</div>
</div>
<div class="form-group">
<label class="sr-only" for="consequence">Missed Reschedule Date Consequence</label>
<div class="col-xs-12 col-sm-6">
<div class="input-group">
<div class="input-group-addon">Consequence</div>
<select id="consequence" class="form-control" ng-model="leagueForm.consequence">
<option value =""></option>
<option value="NONE">N/A</option>
<option value="FORFEIT">Forfeit</option>
<option value="FINE">Fine</option>
</select>
</div>
</div>
<div class="col-xs-12 col-sm-6">
<div class="input-group" ng-show="!fineHidden">
<label class="sr-only" for="fine">Fine</label>
<div class="input-group-addon">$</div>
<input type="text" class="form-control" id="fine" placeholder="fine" ng-model="leagueForm.fine">
<div class="input-group-addon">.00</div>
</div>
</div>
</div>
<button type="submit" class="btn btn-info">Update</button>
<button type="button" class="btn btn-default" ng-click=closeThisDialog("Cancel")>Cancel</button>
</form>
</div>
<div> </div>
</div>
I think it may be due to you passing the controller value as HomeController - which is overwriting the leagueForm value (to empty values) in the $scope as it's spun up.
Resolved. Was very simple after all. Just needed to remove the empty definition of
$scope.leagueForm = {
name: '',
shortname: '',
minAgeGroup: null,
maxAgeGroup: null,
type: null,
rescheduleDays: '',
consequence: '',
fine: '',
logoURL: '',
leagueId: ''
};
from the controller. Then reference leagueForm.name, etc, as the ng-model in the Add dialog, and finally my $scope.openEditLeague function works as it is specified in the original post.

Set validation for dynamic field

I have a form where the user can add fields dynamically. It is my html:
<body ng-controller="FruitController">
<button type="button" ng-click="addFruit()">Add fruit</button>
<form name="list">
<div id="dynamicList" ng-repeat="fruit in fruits">
<input type="text" name="fruitName" ng-model="fruit.name" ng-minlength="3"/>
</div>
</form>
</body>
And it is my controller:
app.controller('FruitController', [function(){
$scope.fruits = [
{name: 'Apple', color: 'red'}
];
$scope.addFruit = function()
{
$scope.fruits.push({name: '', color: ''});
};
}]);
So, when a field is invalid i add a css class with the next directive:
ng-class="{'uk-form-danger': (list.fruitName.$invalid && !list.fruitName.$pristine)}"
The problem is that, when 1 field fails, another fields too.
Any ideas ?
Form inside ng-repeat won't work directly. You need to create a a separate form for inner elements that form will be child of outer form list
<form name="list">
<div id="dynamicList" ng-repeat="fruit in fruits">
<form name="innerForm">
<input type="text" name="fruitName" ng-model="fruit.name" ng-minlength="3"
ng-class="{'uk-form-danger': (innerForm.fruitName.$invalid && !fruit.name.$pristine)}"/>
</form>
</div>
</form>

How to add categories and subcategories in meanjs

I have three linked lists you need to work a bit like a cascading drop-down lists, that is, when you select an item in the first list, the second filter, which filters the third.
i need same like this.[http://jsfiddle.net/benfosterdev/dWqhV/][1]
In this example all data is added static, but i need to add dynamic using module crud in meanjs.
categories controller:
angular.module('categories').controller('CategoriesController', ['$scope', '$stateParams', '$location', 'Authentication', 'Categories',
function($scope, $stateParams, $location, Authentication, Categories) {
$scope.authentication = Authentication;
// Create new Category
$scope.create = function() {
// Create new Category object
var category = new Categories ({
name: this.name
});
// Redirect after save
category.$save(function(response) {
$location.path('categories/' + response._id);
// Clear form fields
$scope.name = '';
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
}
]);
create categories:
<section data-ng-controller="CategoriesController">
<div class="page-header">
<h1>New Category</h1>
</div>
<div class="col-md-12">
<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">
<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>
</div>

Odd duplication in Angular repeater

I am getting some odd behavior when I update the array that a repeater is using from a $watch
This is the HTML
<section data-ng-controller="JobsController">
<div class="page-header">
<h1>New Job</h1>
</div>
<div class="col-md-12">
<form class="form-horizontal" data-ng-submit="create()" novalidate>
<fieldset>
<div class="form-group" data-ng-controller="DisciplinesController" data-ng-init="find()">
<h3>Discipline</h3>
<div>
<!--clicking these will filter -->
<label class="form-control" data-ng-repeat="discipline in disciplines">
<input type="checkbox" checklist-model="$parent.dl" checklist-value="discipline"> {{discipline.name}}
</label>
</div>
</div>
<!--this is the updated list -->
<div class="form-group">
<h3>Roles</h3>
<div>
<label class="form-control" data-ng-repeat="role in selectedDisciplineRoles">
<input type="checkbox" checklist-model="roleList" checklist-value="role"> {{role.name}}
</label>
</div>
</div>
<div class="form-group">
<h3>What "Job" are they trying to do?</h3>
<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">
<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>
</div>
</section>
What I am trying to do is have this model filter on the server and have the client update with the appropriate values
'use strict';
// Jobs controller
angular.module('jobs').controller('JobsController', ['$scope', '$stateParams', '$location', 'Authentication', 'Jobs', 'RolesAPI',
function($scope, $stateParams, $location, Authentication, Jobs, RolesAPI) {
$scope.authentication = Authentication;
$scope.$watchCollection("dl", function(){
var activeDisciplineIds = _.pluck($scope.dl, "_id");
$scope.selectedDisciplineRoles = [];
RolesAPI.getByDisciplineIds(activeDisciplineIds)
.success(function(data){
$scope.selectedDisciplineRoles = data;
console.log($scope.selectedDisciplineRoles)
}
);
});
}
]);
I don't see any duplicates on the return, however when i click on the checkbox there is a quick duplication of the all the active results, and then the duplicates disappear.
I am open to creating an angualar filter but wasn't able to get it working. Here is the data that I am dealing with.
[
{
_id: "547d2ad8b62d3f8bfaf139f8",
user: {
_id: "547648f95413b30000a03e21"
},
base: "547956b0824679a54c9142d2",
__v: 0,
created: "2014-12-02T02:58:32.422Z",
disciplines: [
"5476625147bd3200004bae00"
],
name: "item 1"
},
{
_id: "547d0012b62d3f8bfaf139f7",
user: {
_id: "547648f95413b30000a03e21"
},
base: "547956a6824679a54c9142d1",
__v: 0,
created: "2014-12-01T23:56:02.427Z",
disciplines: [
"5476616347bd3200004badfb",
"547661cb47bd3200004badfd"
],
name: "item 2"
},
{
_id: "547cfea6b62d3f8bfaf139f6",
user: {
_id: "547648f95413b30000a03e21"
},
base: "547956a6824679a54c9142d1",
__v: 0,
created: "2014-12-01T23:49:58.885Z",
disciplines: [
"547661cb47bd3200004badfd",
"5476616347bd3200004badfb"
],
name: "item 3"
}
]
The filtering needs to happen based on a match of an array of ids, and those in the disciplines array of the object.
so something like
["5476616347bd3200004badfb", "547661cb47bd3200004badfd"]
would return item 1 and item 3, not item 2
I ended up getting the filter working like this.
'use strict';
angular.module('roles').filter('rolesByDiscipline', [
function() {
return function(roles, disciplineIds) {
return roles.filter(function(role) {
for (var i in role.disciplines) {
if (_.pluck(disciplineIds, "_id").indexOf(role.disciplines[i]) != -1) {
return true;
}
}return false;
});
};
}
]);
HTML
<div class="form-group" data-ng-controller="RolesController" data-ng-init="find()">
<h3>Roles</h3>
<div>
<label class="form-control" data-ng-repeat="role in roles | rolesByDiscipline:$parent.dl">
<input type="checkbox" checklist-model="roleList" checklist-value="role"> {{role.name}}
</label>
</div>
</div>

Fields values generated using ng-repeat is not getting while submit

Template for form submission. This page will display the form template. Initially it shows the TItle,Full Name. On clicking the 'Add Tags' link new input fields is been generated for entering tags.
On submit, the field input(story.tag) is not been included on RequestPayload
<form novalidate ng-submit="save()">
<div>
<label for="title">Title</label>
<input type="text" ng-model="story.title" id="title" required/>
</div>
<div>
<label for="firstName">Full Name</label>
<input type="text" ng-model="story.fullname" id="fullname" required/>
</div>
<div ng-controller="Note" >
<div ng-repeat="story in items ">
<label>Tag {{$index+1}}:</label>
<input type="text" ng-model="story.tag" id="tag" required/>
</div>
<a ng-click="add()">Add Tags</a>
</div>
<button id="save" class="btn btn-primary">Submit Story</button>
</form>
script :- app.js
angular.module("getbookmarks", ["ngResource"])
.factory('Story', function ($resource) {
var Story = $resource('/api/v1/stories/:storyId', {storyId: '#id'});
Story.prototype.isNew = function(){
return (typeof(this.id) === 'undefined');
}
return Story;
})
.controller("StoryCreateController", StoryCreateController);
function StoryCreateController($scope, Story) {
$scope.story = new Story();
$scope.save = function () {
$scope.story.$save(function (story, headers) {
toastr.success("Submitted New Story");
});
};
}
//add dynamic forms
var Note = function($scope){
$scope.items = [];
$scope.add = function () {
$scope.items.push({
inlineChecked: false,
tag: "",
questionPlaceholder: "foo",
text: ""
});
};
}
The story object inside ng-repeat is in another scope. This JSFiddle should do what you are looking for.
<div ng-app>
<div ng-controller="NoteCtrl">
<form novalidate ng-submit="save()">
<div>
<label for="title">Title</label>
<input type="text" ng-model="story.title" id="title" required/>
</div>
<div>
<label for="firstName">Full Name</label>
<input type="text" ng-model="story.fullname" id="fullname" required/>
</div>
<div ng-repeat="story in items">
<label>Tag {{$index+1}}:</label>
<input type="text" ng-model="story.tag" required/>
</div> <a ng-click="add()">Add Tags</a>
<button id="save" class="btn btn-primary">Submit Story</button>
</form>
<div ng-repeat="test in items">
<label>Tag {{$index+1}}: {{test.tag}}</label>
</div>
</div>
</div>
The NoteController:
function NoteCtrl($scope) {
$scope.story = {};
$scope.items = [];
$scope.story.tag = $scope.items;
$scope.add = function () {
$scope.items.push({
inlineChecked: false,
tag: "",
questionPlaceholder: "foo",
text: ""
});
console.log($scope.story);
};
}

Resources