I would like to be able to select a specific object and enter a text in it 'dynamically' in Angular.
App file:
var myApp = angular.module("myApp", []);
myApp.controller("myCtrl", ["$scope", function($scope){
$scope.persons = [
{
name: "Kevin",
lastName: "Cris",
mottos : [
{
motto: "Holy Moly!"
}
],
},
{
name: "Tres",
lastName: "Yepo",
mottos : [
{
motto: "Crispy!"
}
],
},
{
name: "Prosi",
lastName: "Nani",
mottos : [
{
motto: "I love this!"
}
],
}
];
}]);
I can insert a text in the object in array[1]:
$scope.addMotto = function(){
$scope.persons[1].mottos.push({
motto: $scope.enterMotto
});
};
But, how could I be able to add motto to a person object each time?
To be more clear: What I am trying to do is: Select a person and add motto.
What I can't figure out is: How to create selection of a person object and add on selected object a text.
Html file:
<div ng-controller="myCtrl">
<section ng-repeat="person in persons">
<p class="header">Persons --</p>
<p>Name: {{person.name}}</p>
<p>lastName: {{person.lastName}}</p>
<p ng-repeat="shoutOut in person.mottos" class="motto">Motto: {{shoutOut.motto}} </p>
</section>
<p ng-repet="newMotto in persons.mottos">Your Motto: {{newMotto.motto}} </p>
<p>Enter Motto:<input type="text" ng-model="enterMotto" /></p>
<button ng-click="addMotto()">Submit </button>
</div><!--myCtrl-->
Live: http://jsfiddle.net/9eau9dq2/
If you want to add to each of the person object, here is what you should do - http://jsfiddle.net/k8o8x60w/
$scope.addMotto = function(){
angular.forEach($scope.persons, function(item, i){
item.mottos.push({motto: $scope.enterMotto});
});
};
If you want to add to the selected person object, you will need to keep the selected id with you and update the id whenever a different person is selected and update his motto accordingly.
You could provide a select box like this to allow user to select a person to which you would want to add a motto
<select>
<option ng-repeat="person in persons" value="{{person.name}}">{{ person.name }} {{ person.lastName }}</option>
</select>
and update your method to...
$scope.addMotto = function () {
angular.forEach($scope.persons, function (item, i) {
if (item.name == $scope.selectedperson) {
item.mottos.push({
motto: $scope.enterMotto
});
}
});
};
Updated fiddle : http://jsfiddle.net/k8o8x60w/1/
Note: Would strongly advice you to use some id too in the person object.
i updated your fiddle with some working code!
http://jsfiddle.net/9eau9dq2/1/
You could also use a select box for sure, but that is really similar anyways ;-)
Hope that helps!
Jan
Related
I am getting student details in summary form, just name and surname. I am passing the response to an array in data: data: function(){ return{ studsSummary:[] }}. I am using this stud array in a v-for to create the students dynamically like this: <div>{{studSummary.name}}</div>.
On selecting a student, I am loading the student details in detailed form beneath the summary area. The detailed details have an object inside data with corresponding fields. Let's say just name and surname only for my question. So in data I also have studDetailed : { name: '', surname: ''}. Further more these are now bound to a textfield through v-model='studDetailed.name'. Now since studsSummary[0].name = studDetailed.name I want the former to react to the latter and have any changes reflect in the summary also as I type in the textfield.
What do I have to change please to make this work? I have then tried this.$set(this.studsSummary[0], 'name', this.studDetailed.name) to bind the two (it's ultimately what I want), but that didn't work.
If I understand you correctly, try like following snippet:
(update studsSummary on #input event)
new Vue({
el: '#demo',
data(){
return {
studsSummary: [{id: 1, name: 'aaa', surname: 'AAA'}, {id:2, name: 'bbb', surname: 'BBB'}, {id:3, name: 'ccc', surname: 'CCC'}],
studDetailed: {id: null, name: '', surname: ''}
}
},
methods:{
selectStud(stud) {
this.studDetailed = stud
},
setStud() {
this.studsSummary = this.studsSummary.map((item) =>
item.id !== this.studDetailed.id
? item
: { ...item, ...this.studDetailed }
)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<ul>
<li v-for="(studSummary, i) in studsSummary" :key="i">
<div #click="selectStud(studSummary)">{{studSummary.name}} - {{studSummary.surname}}</div>
</li>
</ul>
<div v-if="studDetailed.id">
<input type="text" v-model="studDetailed.name" #input="setStud" />
<input type="text" v-model="studDetailed.surname" #input="setStud" />
</div>
</div>
My object looks like:
var models = {
"Test1":{
"name":"Test1",
"members":
{
"T1":{//some more properties},
"T2":{//some more properties}
}
}
"Test2":{
"name":"Test2",
"members":
{
"T1":{//some more properties},
"T2":{//somemore properties}
}
}
}
Provided, user selects a property of object models, I want to display the members property of that selected property of models object in a drop down.
Eg. if user selects Test1 property, drop down should be populated with T1 and T2.
Any suggestions regarding question clarity are appreciated.
As you can't change your object, in your HTML you can have:
<div ng-repeat="model in models">
<div>
<p ng-click="toggleVisibility(model.name)">Name: {{model.name}}</p>
<div ng-repeat="member in model.members" ng-if="model.visibility">
<p>Member Name: {{getMemberName(model.name, $index)}} </p>
<p>Member properties: {{getMemberProperties(model.name, $index)}} </p>
</div>
</div>
</div>
And on your AngularJS Controller:
$scope.toggleVisibility = function (entry) {
$scope.models[entry].visibility = !$scope.models[entry].visibility;
};
$scope.getMemberName = function (entry, $index) {
return Object.keys($scope.models[entry].members)[$index];
};
$scope.getMemberProperties = function (entry, $index) {
var key = Object.keys($scope.models[entry].members)[$index];
return $scope.models[entry].members[key];
};
EDIT: Change the answer to fit the requirements.
How can I filter an ng-repeat to show all items where a certain columnfield is an empty string? When I try this by typing nothing in the field it always seem to give the full list (wich is expected). I only want to see the person with id 1. How can I adjust the filter that a certain character in the inputfield makes the ng repeat filter on empty fields for the name column.
FiddleJs Example
My view:
<div class="panel-heading">
<h3>Filtered by {{filterValue}}</h3>
<input ng-change="filter()" ng-model="filterValue"/>
</div>
<div class="panel-body">
<ul class="list-unstyled">
<li ng-repeat="p in filteredPeople">
<h4>{{p.name}} ({{p.age}}) id: {{p.id}}</h4>
</li>
</ul>
</div>
Controller:
var people = [{
name: '',
age: 32,
id: 1
}, {
name: 'Jonny',
age: 34,
id: 2
}, {
name: 'Blake',
age: 28,
id: 3
}, {
name: 'David',
age: 35,
id: 4
}];
$scope.filter = function (value) {
$scope.filteredPeople = $filter('filter')(people, {
name: $scope.filterValue
});
}
$scope.people = people.slice(0);
Delete your $scope.filter() function in the controller and the ng-change="filter()" in your view. You should change var people array to $scope.people. You also need to delete the line $scope.people = people.slice(0);.
Create a filter function in your controller to only return people whose name property is empty if $scope.filterValue is empty:
$scope.emptyFilter = function(person) {
if ($scope.filterValue.length === 0) {
if (person.name.length === 0) {
return person;
}
} else {
return person;
}
};
Next, update your ng-repeat with the following:
<li ng-repeat="p in people | filter:emptyFilter | filter:{name: filterValue}">
I have a AngularJS directive that allows users to select a values from a list to filter on. Pretty simple concept which is represented here:
Problem is when I click one of the checkboxes they all select unintended. My directive is pretty simple so I'm not sure why this is happening. The code around the selection and checkboxes is as follows:
$scope.tempFilter = {
id: ObjectId(),
fieldId: $scope.available[0].id,
filterType: 'contains'
};
$scope.toggleCheck = function (id) {
var values = $scope.tempFilter.value;
if (!values || !values.length) {
values = $scope.tempFilter.value = [];
}
var idx = values.indexOf(id);
if (idx === -1) {
values.push(id);
} else {
values.splice(idx, 1);
}
};
$scope.valuesListValues = function (id) {
return $scope.available.find(function (f) {
return f.id === id;
}).values;
};
and the data resembles:
$scope.available = [{
id: 23,
name: 'Store'
values: [
{ id: 124, name: "Kansas" },
{ id: 122, name: "Florida" }, ... ]
}, ... ]
the view logic is as follows:
<ul class="list-box">
<li ng-repeat="val in valuesListValues(tempFilter.fieldId)">
<div class="checkbox">
<label ng-click="toggleCheck(val.id)">
<input ng-checked="tempFilter.value.indexOf(val.id) === -1"
type="checkbox"> {{val.name}}
</label>
</div>
</li>
</ul>
First off, it toggleCheck fires twice but populates the correct data ( second time given my code it removes it though ).
After the second fire, it checks all boxes... Any ideas?
Perhaps its that the local variable doesn't get reassigned to the property of the scope property used in the view. Since your values are then non-existent and not found, the box is checked.
$scope.tempFilter.value = values
I took the interface concept you were after and created a simpler solution. It uses a checked property, found in each item of available[0].values, as the checkbox model. At the top of the list is a button that clears the selected items.
JavaScript:
function DataMock($scope) {
$scope.available = [{
id: 23,
name: 'Store',
values: [{
id: 124,
name: "Kansas"
}, {
id: 122,
name: "Florida"
}]
}];
$scope.clearSelection = function() {
var values = $scope.available[0].values;
for (var i = 0; i < values.length; i++) {
values[i].checked = false;
}
};
}
HTML:
<body ng-controller="DataMock">
<ul class="list-box">
<li>
<button ng-click="clearSelection()">Clear Selection</button>
</li>
<li ng-repeat="val in available[0].values">
<div class="checkbox">
<label>
<input ng-model="val.checked"
type="checkbox" /> {{val.name}}
</label>
</div>
</li>
</ul>
</body>
Demo on Plunker
The repeat that I used to grab the values based on the id, was the problem area.
<li ng-repeat="val in valuesListValues(tempFilter.fieldId)">
removing that and simple listening and setting a static variable resolved the problem.
$scope.$watch('tempFilter.fieldId', function () {
var fId = $scope.tempFilter.fieldId;
if ($scope.isFieldType(fId, 'valuesList')) {
$scope.valuesListValues = $scope.valuesListValues(fId);
}
}, true);
});
and then in the view:
ng-repeat="value in valuesListValues"
I have an object
$scope.colleges = [{"CollegeCode":"40","CollegeName":"College1"},
{"CollegeCode":"35","CollegeName":"College2"},
{"CollegeCode":"32","CollegeName":"College3"},
{"CollegeCode":"15","CollegeName":"College4"}]
I'm populating a select element with it's contents
<select ng-model="collegeSelection" ng-options="c as c.CollegeName for c in colleges" name="selectCollege"></select>
It renders on the page like so
<select class="ng-pristine ng-valid" name="selectCollege" ng-options="c as c.CollegeName for c in colleges" ng-model="collegeSelection" style="" selected="selected">
<option value="?" selected="selected"></option>
<option value="0">College1</option>
<option value="1">College2</option>
<option value="2">College3</option>
<option value="3">College4</option>
etc....
I'm also binding this select to collegeSelection and when an item is selected the object look like this
$scope.collegeSelection = {"CollegeCode":"32","CollegeName":"College"}
When someone clicks edit on the page, the college I want selected by default comes from the userToUpdate object.
$scope.userToUpdate = {
Id: 1,
FirstName: 'John',
LastName: 'Doe',
CollegeCode: '35,
CollegeName: 'College2',
Active: true
};
When an edit button and the userToUpdate object is populated, I would like the college in the select element to be set to the college in the user object. How could one make this happen? FYI, the value in the rendered select does not match the CollegeCode. It seems angular uses the index from the colleges object. Thanks
Try this one
<select ng-model="collegeSelection" ng-options="c.CollegeCode as c.CollegeName for c in colleges" name="selectCollege"></select>
<span>{{collegeSelection}}</span>
<input type="button" ng-click="switch()" name="switch" value="switch" />
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function ($scope, $filter) {
$scope.colleges = [{ "CollegeCode": "40", "CollegeName": "College1" },
{ "CollegeCode": "35", "CollegeName": "College2" },
{ "CollegeCode": "32", "CollegeName": "College3" },
{ "CollegeCode": "15", "CollegeName": "College4" }
]
$scope.switch = function () {
$scope.collegeSelection = "32";
};
});