Handlebars bind outside each in markup - javascript

I have a problem to bind an object in handlebars outside each "sectorsPressCoverageElements" in a markup.
This is my data that is a json:
{
"name": "Rassegna",
"page": 1,
"pages": 7,
"sectorsPressCoverageElements": [
{
"id": 25129,
"media": "media",
"linkMedia": "",
"article": "article",
"journalist": "",
"linkJournalist": "",
"publishingDate": "2017-11-23T09:00:00",
"purchase": false
},
{
"id": 25129,
"media": "media",
"linkMedia": "",
"article": "article",
"journalist": "",
"linkJournalist": "",
"publishingDate": "2017-11-23T09:00:00",
"purchase": false
}
],
"categories": [
],
"error": null
}
My problem is bind "name" that is outside each.
This my markup with area to bind "data-name" with name (for example in json : "name": "Rassegna"):
<script id="handlePressCoverage" type="text/x-handlebars-template">
{{#each sectorsPressCoverageElements}}
<tr data-id="{{id}}" data-category="0">
#*<td> <input type="checkbox" class="select-element"></td>*#
<td class="col-xs-2">{{#simplifyDate publishingDate}}{{/simplifyDate}}</td>
<text>
<td class="col-xs-1"><button data-id="{{id}}" data-name="{{HOW BIND NAME HERE??}}" class="btn btn-success btn-xs iPressShare">Save &nbsp<i class="iPressIconShare fas fa-share-alt"></i></button></td>
</text>
</tr>
{{/each}}
</script>
And pass data to handlebars:
var sourcePressCoverage = $("#handlePressCoverage").html();
var templatePressCoverage = Handlebars.compile(sourcePressCoverage);
$.getJSON(url, function (data) {
$htmlsourcePressCoverage = $(templatePressCoverage(data));
});

To bind name that is outside each, You can use ../ segments in Handlebar. This will evaluate their paths against a parent context.
For example in your case simply putting ../name in the data-name attribute will result in Rassegna
<script id="handlePressCoverage" type="text/x-handlebars-template">
{{#each sectorsPressCoverageElements}}
<tr data-id="{{id}}" data-category="0">
#*<td> <input type="checkbox" class="select-element"></td>*#
<td class="col-xs-2">{{#simplifyDate publishingDate}}{{/simplifyDate}}</td>
<text>
<td class="col-xs-1"><button data-id="{{id}}" data-name="{{../name}}" class="btn btn-success btn-xs iPressShare">Save &nbsp<i class="iPressIconShare fas fa-share-alt"></i></button></td>
</text>
</tr>
{{/each}}

Related

Bind entire table row with checkbox to reactive data value in Vue3 table

I have a Vue3 form as part of an InertiaJS app (with Laravel) that uses a text field to search the back and and return a matched list of names. I display them in a table for the users to select names, show a list of the selected items, stash them in a local data variable, and then when the form is submitted, pass it to the back end.
<script setup>
import {Head, Link, useForm} from '#inertiajs/inertia-vue3'
import TextInput from '#/Components/ping/TextInput.vue'
import PrimaryButton from '#/Components/PrimaryButton.vue'
import {Inertia} from '#inertiajs/inertia';
import {ref, watch} from 'vue';
import Icon from '#/Components/Icon.vue';
import debounce from 'lodash/debounce';
const form = useForm({
name: '',
checkedNames: []
});
const props = defineProps({
users: Object,
filters: Object,
})
let search = ref('')
let selectedNames = ref([])
watch(search, debounce(value => {
Inertia.get('/admin/areas/create', {search: value}, {preserveState: true, replace: true})
}, 500));
function reset() {
search.value = '';
props.users = '';
}
function searchUsers(search) {
Inertia.visit('/admin/areas/create', {
method: 'get',
data: {search: search},
only: ['users']
})
}
</script>
<script>
import DefaultLayout from '#/Layouts/DefaultLayout.vue';
export default {
layout: DefaultLayout
}
</script>
<template>
<div>
...
<div v-if="search.length > 0">
<table class="table-auto">
<thead>
<tr class="text-left font-bold">
<th class="pb-4 pt-6 px-6 text-sm">Select</th>
<th class="pb-4 pt-6 px-6 text-sm">Name</th>
<th class="pb-4 pt-6 px-6 text-sm">Last Name</th>
<th class="pb-4 pt-6 px-6 text-sm">Member Number</th>
<th class="pb-4 pt-6 px-6 text-sm">Status</th>
</tr>
</thead>
<tbody>
<tr v-for="user in users.data" :key="user.id" class="hover:bg-gray-100 focus-within:bg-gray-100">
<td class="border-t">
<input
type="checkbox"
:value="user.id"
v-model="selectedNames"
/>
</td>
<td class="border-t">
{{ user.first_name }}
</td>
<td class="border-t">
{{ user.last_name }}
</td>
<td class="border-t">
{{ user.member_number }}
</td>
<td class="border-t">
{{ user.status }}
</td>
</tr>
</tbody>
</table>
</div>
<div class="mt-5">
<h2 class="text-lg font-bold">Selected Approvers</h2>
<ul>
<li v-for="selected in selectedNames">{{ selected }}</li>
</ul>
</div>
</div>
</template>
Here is the data in users as it is returned from the back end.
const users = [
{
"id":1,
"member_number":1234,
"first_name":"Richard",
"last_name":"Brown",
"email":"richard#brown.com",
"status":"Active"
},
{
"id":2,
"member_number":2345,
"first_name":"Joe",
"last_name":"Blow",
"email":"joe#blow.com",
"status":"Active"
},
{
"id":3,
"member_number":6789,
"first_name":"Sam",
"last_name":"Snead",
"email":"same#snead.com",
"status":"Inactive"
},
]
My question is, in the Selected Approvers list at the bottom, I want to also display the member_number, first_name, and last_name fields, but I'm currently only binding on the id column. How can I also bind on the other columns so that they are available in the selectedNames variable? Is there a way to a) use a checkbox as I am doing and also b) bind the entire user object to selectedNames?
Select the user id's and place them into a collection of these, as you are doing, and then use this array to filter the users data to show only those users that have been selected. And so in the code example below, I am displaying the selected users (again by use of id) in its own table:
<tbody>
<tr v-for="selected in selectedUsers" :key="selected.id">
<td>
{{ selected.first_name }}
</td>
<td>
{{ selected.last_name }}
</td>
<td>
{{ selected.member_number }}
</td>
<td>
{{ selected.status }}
</td>
</tr>
</tbody>
And I'm providing the data for this table via a calculated property that uses the array of user id's:
const selectedUserIds = ref([]);
const selectedUsers = computed(() => {
return users.value.filter((user) => selectedUserIds.value.includes(user.id));
});
Answer updated as per recommendations by Tao)
My MRE example is below.
You can also run my example code in the Vue SFC Playground here: Playground link
<template>
<div>
<h2>Foo02</h2>
<div class="clearSelected">
<button #click="clearSelected">
Clear All Selected
</button>
</div>
<table>
<thead>
<tr>
<th>Select</th>
<th>Name</th>
<th>Last Name</th>
<th>Member Number</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr v-for="user in users" :key="user.id" #click="toggleRow(user.id)">
<td>
<input type="checkbox" :value="user.id" v-model="selectedUserIds" />
</td>
<td>
{{ user.first_name }}
</td>
<td>
{{ user.last_name }}
</td>
<td>
{{ user.member_number }}
</td>
<td>
{{ user.status }}
</td>
</tr>
</tbody>
</table>
<div>
<h2>Selected Approvers</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Last Name</th>
<th>Member Number</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr v-for="selected in selectedUsers" :key="selected.id">
<td>
{{ selected.first_name }}
</td>
<td>
{{ selected.last_name }}
</td>
<td>
{{ selected.member_number }}
</td>
<td>
{{ selected.status }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script setup>
import { computed, ref } from 'vue';
const selectedUserIds = ref([]);
const selectedUsers = computed(() => {
return users.value.filter((user) => selectedUserIds.value.includes(user.id));
});
const clearSelected = () => {
selectedUserIds.value = [];
}
const toggleRow = (userId) => {
if (selectedUserIds.value.includes(userId)) {
selectedUserIds.value = selectedUserIds.value.filter((id) => id !== userId);
} else {
selectedUserIds.value.push(userId);
}
}
const users = ref(
[
{
"id": 1,
"member_number": 6109,
"first_name": "Richard",
"last_name": "Brown",
"email": "RBrown#fu.com",
"status": "Active"
},
{
"id": 2,
"member_number": 9931,
"first_name": "Joe",
"last_name": "Blow",
"email": "JBlow#fu.com",
"status": "Inactive"
},
{
"id": 3,
"member_number": 8292,
"first_name": "Sam",
"last_name": "Snead",
"email": "SSnead#fu.com",
"status": "Inactive"
},
{
"id": 4,
"member_number": 4741,
"first_name": "Donald",
"last_name": "Duck",
"email": "DDuck#fu.com",
"status": "Active"
},
{
"id": 5,
"member_number": 8839,
"first_name": "Micky",
"last_name": "Mouse",
"email": "MMouse#fu.com",
"status": "Active"
},
{
"id": 6,
"member_number": 2692,
"first_name": "John",
"last_name": "Doe",
"email": "JDoe#fu.com",
"status": "Active"
},
{
"id": 7,
"member_number": 9843,
"first_name": "George",
"last_name": "Washington",
"email": "GWashington#fu.com",
"status": "Inactive"
},
{
"id": 8,
"member_number": 6452,
"first_name": "Abraham",
"last_name": "Lincoln",
"email": "ALincoln#fu.com",
"status": "Inactive"
},
{
"id": 9,
"member_number": 4918,
"first_name": "John",
"last_name": "Lennon",
"email": "JLennon#fu.com",
"status": "Active"
},
{
"id": 10,
"member_number": 3459,
"first_name": "Phil",
"last_name": "Simms",
"email": "PSimms#fu.com",
"status": "Inactive"
},
{
"id": 11,
"member_number": 2447,
"first_name": "James",
"last_name": "Bond",
"email": "JBond#fu.com",
"status": "Active"
},
{
"id": 12,
"member_number": 2142,
"first_name": "Bugs",
"last_name": "Bunny",
"email": "BBunny#fu.com",
"status": "Active"
},
{
"id": 13,
"member_number": 995,
"first_name": "Fred",
"last_name": "Flinstone",
"email": "FFlinstone#fu.com",
"status": "Inactive"
}
]
);
</script>
<style scoped>
table {
margin: auto;
border-collapse: collapse;
border: 1px solid #FF0000;
}
th {
padding: 5px 25px;
text-align: left;
margin: 0px;
border: 1px solid black;
}
td {
padding: 5px 25px;
text-align: left;
margin: 0px;
border: 1px solid black;
}
.clearSelected {
margin: 1em;
}
</style>
I was actually able to solve my problem withe a slight variation on the answer by Hovercraft above by binding the value of the entire object to the checkbox:
<tr v-for="user in users.data" :key="user.id" class="hover:bg-gray-100 focus-within:bg-gray-100">
<td class="border-t">
<input
type="checkbox"
:value="user"
v-model="form.selectedNames"
/>
</td>
<td class="border-t">
{{ user.first_name }}
</td>
<td class="border-t">
{{ user.last_name }}
</td>
<td class="border-t">
{{ user.member_number }}
</td>
<td class="border-t">
{{ user.status }}
</td>
</tr>
As pointed out by #tao, I needed selectedNames to outlive a more volatile users page, since this could change due to server side pagination (as compared to storing all values in the component and just paging through them).
I also had to update it to bind to form.selectedNames, since that is the form values that are submitted by the InertiaJS form helper.
const form = useForm({
name: '',
selectedNames: []
});

How to dynamically loop all values in a json string

I'm creating a project in Vue.js
I need to loop through a JSON object but can't find out how to access this.
what I got:
"functionality": {
"uitgifte": {
"image": "",
"value": "Handmatige capsule inname en uitgifte",
"label": "",
"splash": true,
"compare": false
},
"schakelaar": {
"image": "",
"value": "Automatische en programmeerbare aan/uit schakelaar",
"label": "",
"splash": true,
"compare": false
},
"kopjesrooster": {
"image": "",
"value": "Draaibaar kopjesrooster voor latte macchiato-glazen",
"label": "",
"splash": true,
"compare": false
},
"ontkalking": {
"image": "",
"value": "Automatische melding voor ontkalking",
"label": "",
"splash": true,
"compare": false
},
"kopgroottes": {
"image": "",
"value": "Programmeerbare kopgroottes",
"label": "",
"splash": true,
"compare": false
}
},
and the html:
<div class="tab">
<table>
<tbody>
<tr>
<td>{{ main.pageCopy.functionele_specificaties }}</td>
</tr>
<tr>
<td v-for="functionality in machine.functionality.uitgifte.value" :key="functionality">{{ machine.functionality.uitgifte.value }}</td>
<td>
<img src="" alt="">
</td>
</tr>
</tbody>
</table>
</div>
The part that says machine.functionality.uitgifte.value I need the "uitgifte" part to be dynamic so it loops through all the elements like it in the JSON. So "uitgifte, schakelaar, kopjesrooster" etc.
Would be awesome if anyone knows the trick.
Thanks.
You simply start your for loop at a higher object level:
<div class="tab">
<table>
<tbody>
<tr>
<td>{{ main.pageCopy.functionele_specificaties }}</td>
</tr>
<tr>
<td v-for="(functionality, index) in machine.functionality" :key="index">
{{ functionality.value }}</td>
<td>
<img src="" alt="">
</td>
</tr>
</tbody>
</table>
</div>
BTW: If you have control of the datasource, make sure to provide an ID for each object and use that ID as the key of the v-for loop.

AngularJS nested ng-repeat in table

I am new to AngularJs and have come across an issue with Json data with nested arrays.
I have simplified the code to a simple html doc, this can be found below.
The first property {{HelloMessage}} is working and gets populated with the string value stored in the property HelloMessage, but the ng-repeat is not.
After looking online, I discovered that I in fact had an array within an array, so assumed that I needed to have an ng-repeat within an ng-repeat, but it is not working. I am quite sure that it is something simple that I have done wrong.
<!DOCTYPE html>
<html ng-app="app">
<head>
<title></title>
</head>
<body>
<h1 ng-controller="myController">{{helloMessage}}</h1>
<div>
<table>
<thead>
<tr>
<th>Id</th>
<th>UserId</th>
<th>DisplayName</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="stream in Data.Records">
<tr ng-repeat="record in stream.Users">
<td>{{stream.Id}}</td>
<td>{{stream.User}}</td>
<td>
{{stream.Description}}
</td>
<!--<td>
<table>
<tbody>
<tr ng-repeat="b in value">
<td>{{b.user}}</td>
</tr>
</tbody>
</table>
</td>-->
</tr>
</tr>
</tbody>
</table>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script type="text/javascript">
angular.module('app', []).controller('myController',
function ($scope) {
$scope.helloMessage = "Hi";
$scope.Data = [{
Success: true,
ErrorMessage: null,
SuccessMessage: null,
Records: [{
"CreatedBy": "Mickey Mouse",
"CreatedDate": "2015-08-17T13:16:22.713",
"CreatedDateDisplay": "17-08-2015",
"Description": "Test 1",
"Id": 7546798576985769857,
"Name": "Test 1",
"UpdatedBy": "",
"UpdatedDate": null,
"UpdatedDateDisplay": null,
"User": null,
"UserId": 0,
"Users": [{
"Users": [{
"Id": 7546798576985769858,
"UserId": 7546798576985769857,
"DisplayName": "Daffy Duck"
}, {
"Id": 7546798576985769859,
"UserId": 7546798576985769857,
"DisplayName": "Pluto"
}
],
"User": "Bugs Bunny",
"UserId": 7546798576985769857,
"Name": "Test 2",
"Description": "Test 2",
"Id": 7546798576985769857,
"CreatedBy": "Goofy",
"CreatedDate": "2015-08-25T14:03:28.083",
"UpdatedBy": "Porky Pig",
"UpdatedDate": "2017-03-27T08:19:36.077",
"CreatedDateDisplay": "25-08-2015",
"UpdatedDateDisplay": "27-03-2017"
}
]
}
]
}
];
});
</script>
</body>
</html>
No errors are throw in Chrome Console
Rewrite the ng-repeat as
<tr ng-repeat="stream in Data[0].Records[0].Users[0].Users">
</tr>
Use
<td>{{stream.Id}}</td>
<td>{{stream.UserId}}</td>
<td>{{stream.DisplayName}}</td>
instead of
<td>{{stream.Id}}</td>
<td>{{stream.User}}</td>
<td>{{stream.Description}}</td>
function myController($scope) {
$scope.helloMessage = "Hi";
$scope.Data = [{
Success: true,
ErrorMessage: null,
SuccessMessage: null,
Records: [{
"CreatedBy": "Mickey Mouse",
"CreatedDate": "2015-08-17T13:16:22.713",
"CreatedDateDisplay": "17-08-2015",
"Description": "Test 1",
"Id": 7546798576985769857,
"Name": "Test 1",
"UpdatedBy": "",
"UpdatedDate": null,
"UpdatedDateDisplay": null,
"User": null,
"UserId": 0,
"Users": [{
"Users": [{
"Id": 7546798576985769858,
"UserId": 7546798576985769857,
"DisplayName": "Daffy Duck"
}, {
"Id": 7546798576985769859,
"UserId": 7546798576985769857,
"DisplayName": "Pluto"
}],
"User": "Bugs Bunny",
"UserId": 7546798576985769857,
"Name": "Test 2",
"Description": "Test 2",
"Id": 7546798576985769857,
"CreatedBy": "Goofy",
"CreatedDate": "2015-08-25T14:03:28.083",
"UpdatedBy": "Porky Pig",
"UpdatedDate": "2017-03-27T08:19:36.077",
"CreatedDateDisplay": "25-08-2015",
"UpdatedDateDisplay": "27-03-2017"
}]
}]
}];
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
<div ng-app>
<div ng-controller="myController">
<h1>{{helloMessage}}</h1>
<table>
<thead>
<tr>
<th>Id</th>
<th>UserId</th>
<th>DisplayName</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="stream in Data[0].Records[0].Users[0].Users">
<td>{{stream.Id}}</td>
<td>{{stream.UserId}}</td>
<td>
{{stream.DisplayName}}
</td>
</tr>
</tbody>
</table>
</div>
</div>
First you have to define your controller to body level as following.
<body ng-controller="myController">
You have defined it as h1 level so it is not accessible.
I have made changes in your code please as following.
<!DOCTYPE html>
<html ng-app="app">
<head>
<title></title
</head>
<body ng-controller="myController">
<h1>{{helloMessage}}</h1>
<div>
<table>
<thead>
<tr>
<th>Id</th>
<th>UserId</th>
<th>DisplayName</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="stream in Data[0].Records[0].Users[0].Users">
<td>{{stream.Id}}</td>
<td>{{stream.UserId}}</td>
<td>{{stream.DisplayName}}
</td>
</tr>
</tbody>
</table>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script type="text/javascript">
angular.module('app', []).controller('myController',
function ($scope) {
$scope.helloMessage = "Hi";
$scope.Data = [{
Success: true,
ErrorMessage: null,
SuccessMessage: null,
Records: [{
"CreatedBy": "Mickey Mouse",
"CreatedDate": "2015-08-17T13:16:22.713",
"CreatedDateDisplay": "17-08-2015",
"Description": "Test 1",
"Id": 7546798576985769857,
"Name": "Test 1",
"UpdatedBy": "",
"UpdatedDate": null,
"UpdatedDateDisplay": null,
"User": null,
"UserId": 0,
"Users": [{
"Users": [{
"Id": 7546798576985769858,
"UserId": 7546798576985769857,
"DisplayName": "Daffy Duck"
}, {
"Id": 7546798576985769859,
"UserId": 7546798576985769857,
"DisplayName": "Pluto"
}],
"User": "Bugs Bunny",
"UserId": 7546798576985769857,
"Name": "Test 2",
"Description": "Test 2",
"Id": 7546798576985769857,
"CreatedBy": "Goofy",
"CreatedDate": "2015-08-25T14:03:28.083",
"UpdatedBy": "Porky Pig",
"UpdatedDate": "2017-03-27T08:19:36.077",
"CreatedDateDisplay": "25-08-2015",
"UpdatedDateDisplay": "27-03-2017"
}]
}]
}];
});
</script>
</html>
Hope this will help you.
thanks
Thank you, thank you all for your help. I have used Geethu Jose answer, but it still did not give me exactly what I was looking for, but after much head scratching I did come up with a solution for my problem. Instead of using the array placeholders [0] I needed access the arrays themselves at the different levels, so I had to change the code to the following.
<div ng-app>
<div ng-controller="myController">
<h1>{{helloMessage}}</h1>
<table>
<tbody>
<tr ng-repeat="data in Data">
<td>
<table ng-repeat="records in data">
<thead>
<tr>
<th>UserId</th>
<th>User</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{records.UserId}}</td>
<td>{{records.User}}</td>
<td>{{records.Name}}</td>
<td>
<table>
<thead>
<tr>
<th>Id</th>
<th>UserId</th>
<th>DisplayName</th>
</tr>
</thead>
<tr ng-repeat="streamUser in records.Users">
<td>{{streamUser.Id}}</td>
<td>{{streamUser.UserId}}</td>
<td>{{streamUser.DisplayName}}</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
It seems that your JSON is full of arrays. It could probably be improved, but there is how you can display it in its current state. You don't need to nest ng-repeat:
<tbody>
<tr ng-repeat="user in Data[0].Records[0].Users[0].Users">
<td>{{user.Id}}</td>
...
</tbody>
Working JSFiddle of your code

How to filter data from json

I'm curently working on some project with angularJS and I'm stuck on this problem. I have one question, it's about filters in angularJS.I don't know how to filter one specific property from JSON.
Here is part of my index page
index.html
<div class="container2">
<table class="table table-hover" ng-hide="hideTable2">
<tr>
<th>Site URL</th>
<th>Group</th>
<th>Edit</th>
</tr>
<tr ng-repeat="site in promise.sites | filter:{group:[""]}" >
<td>
<a href="http://{{site.url}}" style="color:{{site.color}}; text-decoration:none">
{{ ::site.siteName }} </a>
<td>
<div class = "btn-group">
<button type = "button" class = "btn btn-primary"> Groups
<span class="badge">{{ ::site.group.length }}</span>
</button>
<button type = "button" class = "btn btn-primary dropdown-toggle" data-toggle = "dropdown">
<span class = "caret"></span>
<span class = "sr-only">Toggle Dropdown</span>
</button>
<ul class = "dropdown-menu" role = "menu" >
<li ng-repeat="g in site.group"><span>{{::g}}</span><hr></li>
</ul>
</div>
<td>
<button class="btn btn-primary" ng-click="toggleEditSites()">Edit</button>
</td>
<td>
<img src="images/glyphicons-208-remove.png" ng-click="deleteSites(site.id)"/>
</td>
</tr>
</table>
Here is JSON structure:
data.json
{
"sites":[
{
"id": 1,
"siteName":"Google",
"url": "www.google.com",
"color": "green",
"group": ["Social","Sport","Games","News","Programming"]
},
{
"id": 2,
"siteName":"Facebook",
"url": "www.facebook.com",
"color": "blue",
"group": []
},
{
"id": 3,
"siteName":"B92",
"url": "www.b92.net",
"color": "red",
"group": ["Social","Sport"]
},
{
"id": 4,
"siteName":"9GAG",
"url": "www.9gag.com",
"color": "purple",
"group": []
}
],
"groups":[
{
"id":1,
"name":"Search Engine",
"color":"green",
"sites":["Google","Yahoo","Bing"]
},
{
"id":2,
"name":"Social",
"color":"red",
"sites":[]
},
{
"id":3,
"name":"Games",
"color":"blue",
"sites":[]
},
{
"id":4,
"name":"Informations",
"color":"red",
"sites":[]
},
{
"id":5,
"name":"Sport",
"color":"orange",
"sites":[]
},
{
"id":6,
"name":"Television",
"color":"green",
"sites":[]
}
]
}
I want to filter by group property in "sites" array.I would be very happy if someone can explain this to me.Thank you very much.

AngularJS <select> two way data binding for <option> coming from AJAX call

I have this Controller:
JApp.controller('WebsiteController', function($scope, $resource) {
var UsersService = $resource('/auth/users', {});
$scope.adding = false;
$scope.users = [];
$scope.addUser = function() {
$scope.adding = true;
UsersService.query({}, function(data) {
$scope.users = data;
$scope.selectedUser = data[0];
});
}
$scope.cancelAddUser = function() {
$scope.adding = false;
}
});
My HTML:
<section class="vbox" ng-controller="WebsiteController">
<section class="panel animated fadeInDown">
<header class="panel-heading">
<h3>{{selectedUser.last_name}} </h3> <!-- Just to test I print it here -->
</header>
<div class="panel-body m-b">
<div class="row text-sm wrapper">
#if (role_admin())
<i class="icon-plus"></i> New Website
#endif
</div>
<div class="table-responsive">
<table class="table table-striped b-t text-sm">
<thead>
<tr>
<th>URL</th>
<th>Assigned to</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<!-- Outside this <tr> doesn't work -->
<tr ng-repeat="website in websites">
<td> {{website.url}}</td>
<td>
<span ng-repeat="assigned in website.users"> <span class="label label-info"> {{assigned.first_name}} </span> </span>
<a ng-click="addUser()" ng-hide="adding" class="btn btn-success btn-xs"> Add new </a></span>
<select ng-hide="!adding"
name="myselect"
ng-model="selectedUser"
ng-options="u.first_name for u in users">
</select>
Cancel
<input type="text" ng-model="selectedUser.first_name"> <!-- It works here! -->
</td>
<td>
<i class="icon-pencil"></i> Edit
</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
</section>
Updated: Notice that it works in my <input> next to the <select>, but doesn't work in my <header> (only binds once)
So when I click on the add user, the AJAX call will retrieve list of users, and successfully show it in the <select> and by default, selectedUser will be pointing at data[0] which is the first user. But now the two way binding is now bound to data[0] instead. If I change my selection to other user, selectedUser is not updated. But if I update my selectedUser, let's say the name, the name in the dropdown list also change.
I have tried not using the line
$scope.selectedUser = data[0];
but still doesn't work anyway, it is not bound at all though I specify ng-model="selectedUser".
The JSON returned:
[
{
"id": 1,
"role_id": 1,
"created_at": "2013-09-19 05:54:36",
"updated_at": "2013-09-19 05:54:36",
"email": "admin#admin.com",
"username": "admin",
"first_name": "Admin",
"last_name": "Istrator"
},
{
"id": 2,
"role_id": 2,
"created_at": "2013-09-19 05:54:36",
"updated_at": "2013-09-19 05:54:36",
"email": "johndoe#gmail.com",
"username": "john",
"first_name": "John",
"last_name": "Doe"
}
]
Anyone can help me with this? I am trying not to go down the $digest or $apply road if I don't have to.
UPDATE 2
The source of the problem is if I try to print out selectedUser outside of the following ng-repeat in my above HTML:
<tr ng-repeat="website in websites"> ...... </tr>
Fiddle to illustrate my problem: http://jsfiddle.net/jofrysutanto/4nfyV/3/
Try This
HTML:
<div ng-app="myApp">
<section class="vbox" ng-controller="WebsiteController">
<section class="panel animated fadeInDown">
<header class="panel-heading">
<h3>{{mySelectedUser.last_name}} </small> <!-- Just to test I print it here -->
</header>
<div class="panel-body m-b">
<div class="table-responsive">
<table class="table table-striped b-t text-sm">
<thead>
<tr>
<th>URL</th>
<th>Assigned to</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="website in websites">
<td>
<span ng-repeat="assigned in website.users"> <span class="label label-info"> {{assigned.first_name}} </span> </span>
<a ng-click="addUser()" ng-hide="adding" class="btn btn-success btn-xs"> Add new </a></span>
<select ng-hide="!adding"
name="myselect"
ng-model="selectedUser"
ng-change="abc(selectedUser)"
ng-options="u.first_name for u in users">
</select>
Cancel
<input type="text" ng-model="selectedUser.first_name"> <!-- It works here! -->
</td>
<td>
<i class="icon-pencil"></i> Edit
</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
</section>
</div>
Controller :
var JApp = angular.module('myApp', []);
JApp.controller('WebsiteController', function($scope) {
//var UsersService = $resource('/auth/users', {});
$scope.adding = false;
$scope.users = [];
$scope.websites = [
{
"id": 1,
"url": "www.google.com",
"cms": "Wordpress"
}
];
$scope.addUser = function() {
$scope.adding = true;
var data = [
{
"id": 1,
"role_id": 1,
"created_at": "2013-09-19 05:54:36",
"updated_at": "2013-09-19 05:54:36",
"email": "admin#admin.com",
"username": "admin",
"first_name": "Admin",
"last_name": "Istrator"
},
{
"id": 2,
"role_id": 2,
"created_at": "2013-09-19 05:54:36",
"updated_at": "2013-09-19 05:54:36",
"email": "johndoe#gmail.com",
"username": "john",
"first_name": "John",
"last_name": "Doe"
}
];
// UsersService.query({}, function(data) {
$scope.users = data; // suppose data is coming from UsersService.query
$scope.selectedUser = data[1];
$scope.mySelectedUser = $scope.selectedUser ;
// });
}
$scope.abc = function(a) {
$scope.mySelectedUser = a;
}
$scope.cancelAddUser = function() {
$scope.adding = false;
}
});
See DEMO
The value of the select dropdown options is u.first_name, so either do this:
$scope.selectedUser = data[0].first_name;
Or change it to use ids or something like this.
ng-options="u.id as u.first_name for u in users"
$scope.selectedUser = data[0].id;

Categories