I am using Angular JS (1.6) application. Inside my app I have components -
oprExternalInstructionsApp ->
oprScriptListPanel ->
I have <opr-list> component in my oprScriptListPanel templete file. I am passing $ctrl.externalInstructionsFiltered in <opr-script-list-panel>
Like items="$ctrl.externalInstructionsFiltered"
but I don’t see {{$ctrl.externalInstructionsFiltered}} is having any data inside my templete oprScriptListPanel.
My template code -
<opr-script-list-panel
items="$ctrl.externalInstructionsFiltered"
toolbar-buttons="$ctrl.toolbarButtons"
selected-items="$ctrl.selectedInstructions"
on-search="$ctrl.filterExternalInstructionsChanged(text)"
on-double-click="$ctrl.edit(item)"
item-actions="$ctrl.itemActions"
item-tags="$ctrl.itemTags"></opr-script-list-panel>
in <opr-script-list-panel component I am passing items -
this.externalInstructionsFiltered = [{
"id": "1",
"displayName": "abc",
"description": "aqaa",
"timeout": "3000",
"isEnabled": "false",
"isReadOnly":"false",
"stepId":"ExternalInterface",
"version":"1",
"artifactOrigin":"custom",
"filterId":"qwq" ,
"filterName":"sdsf",
"Script": "abc",
"active": true,
"winner": true,
"icon": "abc"
}];
Component file for opr-script-list-panel
import './oprScriptListPanel.template.html';
var oprScriptListPanelComponent = {
templateUrl: 'oprScriptListPanel.template.html',
bindings: {
toolbarButtons: "<?",
selectedItems: "#?",
onSearch:"&?",
items:"=?",
data:"=ngModel",
oprListDeleteMode:"&?",
onDoubleClick:"&?",
itemActions:"&?",
itemTags:"&?"
}
};
export default oprScriptListPanelComponent;
Template file-
<div>
<opr-toolbar
buttons="$ctrl.toolbarButtons"
selected-items="$ctrl.selectedInstructions"
filter-placeholder="Filter instructions"
on-search="$ctrl.filterExternalInstructionsChanged(text)"
show-first-separator="true">
</opr-toolbar>
</div>
<div class="empty-info" ng-if="$ctrl.externalInstructionsFiltered && !$ctrl.externalInstructionsFiltered.length">
<p ng-bind=":: 'opr.external.instructions.emptyList' | oprL10n"></p>
</div>
{{$ctrl.externalInstructionsFiltered}}
{{$ctrl.selectedInstructions}}
I am not getting any data for {{$ctrl.externalInstructionsFiltered}}, But if I will print {{$ctrl.toolbarButtons"}} I am able to see some array. I checked module reference is correct. I am not getting any error.
Related
I have code that generates my react UI, and it works with a list of languages to generate checkboxes for language selection. For example when in state
languages = {English: true, French: false}
however when i change it to an object which contains the values from the DB, I get no error, but nothing loads.
[
{
"language_name": "English",
"lang_num": 1,
"checked": false
},
{
"language_name": "Mandarin Chinese",
"lang_num": 2,
"checked": false
},
]
The code is:
{
Object.entries(this.props.languages).forEach(([key, value]) => {
console.log(this.props.languages[key].language_name),
<label id="checkbox-margin">
<input
type="checkbox"
value={this.props.languages[key].language_name}
checked={this.props.languages[key].checked}
onChange={this.handleLangClick}
/> {this.props.languages[key].language_name}
</label>
}
)
The console.log lists each language string fine, i get them all printed in the console, but nothing is generated on the UI. Any idea why?
Thanks!
Try to use the map function to iterate through the array:
{this.props.languages ? this.props.languages.map(language => {
return (
<label id="checkbox-margin" key={language.lang_num}>
<input
type="checkbox"
value={language.language_name}
checked={language.checked}
onChange={this.handleLangClick}
/> {language.language_name}
</label>
)}) : 'Loading languages...'
}
I am trying to set some objects in a Bootstrap-Vue form select which I get via JSON.
The JSON is made up of teacher objects from the following fields:
[
{
"id": 1,
"name": "John",
"surname": "Doe",
"email": "john.doe#gmail.com"
}
]
What I'm trying to do is put the name and surname in the select list, that is the full name.
I have already managed to do this via a computed property by processing the list.
But now I want that when I select a teacher, the list of courses is filtered according to the chosen teacher.
To do this I need the teacher's email, which I can't recover, having processed the teachers to get the full name.
Consequently, I can't even update the list of courses based on the teacher chosen.
This is the code for the template:
<b-form-group
id="input-group-3"
label="Docente:"
label-for="input-3"
>
<b-form-select
v-model="teacher"
:options="teachers"
value-field="item"
text-field="fullName"
required
#change="filterCourse"
></b-form-select>
<div class="mt-3">
Selected: <strong>{{ teacher }}</strong>
</div>
</b-form-group>
This is the script code:
import { mapGetters, mapActions } from "vuex";
export default {
data() {
return {
teacher: "",
course: "",
};
},
created: function() {
this.GetActiveTeachers();
this.GetActiveCourses();
},
computed: {
...mapGetters({
ActiveTeacherList: "StateActiveTeachers",
ActiveCourseList: "StateActiveCourses",
FilteredTeacherList: "StateTeacherByCourse",
FilteredCourseList: "StateCourseByTeacher",
}),
teachers: function() {
let list = [];
this.ActiveTeacherList.forEach((element) => {
let teacher = element.name + " " + element.surname;
list.push(teacher);
});
return list;
},
},
methods: {
...mapActions([
"GetActiveTeachers",
"GetActiveCourses",
"GetCourseByTeacher",
"GetTeacherByCourse",
"AssignTeaching",
]),
async filterCourse() {
const Teacher = {
teacherEmail: "john.doe#gmail.com", // For testing purpose
};
try {
await this.GetCourseByTeacher(Teacher);
} catch {
console.log("ERROR");
}
},
async filterTeacher() {
const Course = {
title: "Programming", // For testing purpose
};
try {
await this.GetTeacherByCourse(Course);
} catch {
console.log("ERROR");
}
},
},
};
You're currently using the simplest notation that Bootstrap Vue offers for form selects, an array of strings.
I suggest you switch to use their object notation, which will allow you to specify the text (what you show in the list) separately from the value (what's sent to the select's v-model).
This way, you'll be able to access all the data of the teacher object that you need, while still being able to display only the data you'd like.
We can do this by swapping the forEach() in your teachers computed property for map():
teachers() {
return this.ActiveTeacherList.map((teacher) => ({
text: teacher.name + " " + teacher.surname,
value: teacher
}));
},
Then, all you need to do is update your filterCourse() handler to use the new syntax, eg.:
async filterCourse() {
const Teacher = {
teacherEmail: this.teacher.email,
};
try {
await this.GetCourseByTeacher(Teacher);
} catch {
console.log("ERROR");
}
},
As a final note, if you don't want or need the full object as the value, then you can mold it to be whatever you need, that's the beauty of this syntax.
For example, you want the full name and email, instead of the parts:
value: {
fullName: teacher.name + " " + teacher.surname,
email: teacher.email
}
Here's two different options you can do.
One would be to generate the <option>'s inside the select yourself, using a v-for looping over your teachers, and binding the email property to the value, and displaying the name and surname inside the option.
This will make your <b-select>'s v-model return the chosen teachers e-mail, which you can then use in your filter.
new Vue({
el: '#app',
data() {
return {
selectedTeacher: null,
activeTeachers: [{
"id": 1,
"name": "Dickerson",
"surname": "Macdonald",
"email": "dickerson.macdonald#example.com"
},
{
"id": 2,
"name": "Larsen",
"surname": "Shaw",
"email": "larsen.shaw#example.com"
},
{
"id": 3,
"name": "Geneva",
"surname": "Wilson",
"email": "geneva.wilson#example.com"
}
]
}
}
})
<link href="https://unpkg.com/bootstrap#4.5.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.css" rel="stylesheet" />
<script src="https://unpkg.com/vue#2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.js"></script>
<div id="app">
<b-select v-model="selectedTeacher">
<option v-for="teacher in activeTeachers" :value="teacher.email">
{{ teacher.name }} {{ teacher.surname }}
</option>
</b-select>
{{ selectedTeacher }}
</div>
The other option would be to change your computed to return an array of objects instead of simple strings as you're currently doing.
By default <b-select> expects the properties value and text if you use an array of objects in the options prop.
Here you would bind the email for each teacher to the value, and the name and surname to the text prop.
This will make your <b-select>'s v-model return the chosen teachers e-mail, which you can then use in your filter.
Reference: https://bootstrap-vue.org/docs/components/form-select#options-property
new Vue({
el: '#app',
data() {
return {
selectedTeacher: null,
activeTeachers: [{
"id": 1,
"name": "Dickerson",
"surname": "Macdonald",
"email": "dickerson.macdonald#example.com"
},
{
"id": 2,
"name": "Larsen",
"surname": "Shaw",
"email": "larsen.shaw#example.com"
},
{
"id": 3,
"name": "Geneva",
"surname": "Wilson",
"email": "geneva.wilson#example.com"
}
]
}
},
computed: {
teacherOptions() {
return this.activeTeachers.map(teacher => ({
value: teacher.email,
text: `${teacher.name} ${teacher.surname}`
}));
}
}
})
<link href="https://unpkg.com/bootstrap#4.5.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.css" rel="stylesheet" />
<script src="https://unpkg.com/vue#2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.js"></script>
<div id="app">
<b-select v-model="selectedTeacher" :options="teacherOptions"></b-select>
{{ selectedTeacher }}
</div>
Requirement:
Showing dynamic data using ngx-datatable and use paging using page id
Description :
I have a dynamic data where I am displaying it using the ngx-datatable in angular and here everything works but the issue I m not sure how to apply the paging using the page_id (sent to the server using post body). Here I am getting the page_id along with the API response this is 1st API call. here page_id has to be sent as a body for the very same API for getting the rest of results.
Ex: Suppose I have 20 results in the 1ST API call I will get the 10 records and a page id by using the page id how can I get the next 10 results
What I implemented:
Getting data and displaying it in table basic paging applied
Below is my code :
Result=[];
reorderable: boolean = true;
selected = [];
rows = [];
columns = [];
DataArray = [];
Results = {
"data": [
{
"_score": 0.36464313,
"_type": "data",
"_id": "abcd",
"_source": {
"filter": "data",
"information": {
"product_id": "abcd",
"creation_utctime": "1477335693653"
},
"enduser": "free"
},
"_index": "dell_laptop"
},
{
"_score": 0.36464314,
"_type": "data",
"_id": "abcde",
"_source": {
"filter": "data",
"information": {
"product_id": "abcde",
"creation_utctime": "1477335693653"
},
"enduser": "free"
},
"_index": "lenovo_laptop"
},
{
"_score": 0.36464314,
"_type": "data",
"_id": "abcdef",
"_source": {
"filter": "data",
"information": {
"product_id": "abcde",
"creation_utctime": "1477335693653"
},
"enduser": "free"
},
"_index": "lenovo_laptop"
}
],
"total": 4,
"page_id": "WpNdVJMMjlJVnJTYTFuUklB"
}
LoadInfo(){
this.DataArray = ["filter","information.product_id","information.creation_utctime","enduser"];
this.rows=[];
this.Result = this.Results['data'];
// tslint:disable-next-line: forin
for (var res in this.Result) {
var row = {};
for (var key in this.Result[res]['_source']) {
if (typeof this.Result[res]['_source'][key] === 'object') {
for (var k in this.Result[res]['_source'][key]) {
let temp = key + "." + k;
row[temp] = this.Result[res]['_source'][key][k];
}
} else {
row[key] = this.Result[res]['_source'][key]
}
row['_id'] = this.Result[res]['_id'];
}
this.rows.push(row);
}
console.log(this.rows);
}
onActivate(event) {
// console.log('Activate Event', event);
}
onSelect({ selected }) {
// console.log('Select Event', selected, this.selected);
this.selected.splice(0, this.selected.length);
this.selected.push(...selected);
}
HTML Code:
<button type="button" (click)="LoadInfo()">LoadData</button>
<div>
<ngx-datatable class="material ui" [rows]="rows" [columnMode]="'force'" [headerHeight]="50"
[footerHeight]="50" [limit]="2" [rowHeight]="'auto'" [reorderable]="reorderable" [selected]="selected"
[selectionType]="'checkbox'" [scrollbarH]="true" [sortType]="'multi'" (activate)="onActivate($event)"
(select)='onSelect($event)'>
<ngx-datatable-column [width]="30" [sortable]="true" [canAutoResize]="false" [draggable]="false"
[resizeable]="false" class="uih">
<ng-template ngx-datatable-header-template let-value="value" let-allRowsSelected="allRowsSelected"
let-selectFn="selectFn">
<input type="checkbox" [checked]="allRowsSelected" (change)="selectFn(!allRowsSelected)" />
</ng-template>
<ng-template ngx-datatable-cell-template let-value="value" let-isSelected="isSelected"
let-onCheckboxChangeFn="onCheckboxChangeFn">
<input type="checkbox" [checked]="isSelected" (change)="onCheckboxChangeFn($event)" />
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column *ngFor="let attr of DataArray" [sortable]="true" prop={{attr}} name={{attr}}>
</ngx-datatable-column>
</ngx-datatable>
</div>
Stackblitz link: https://stackblitz.com/edit/angular-secw8u
Note: even though if there is pageid also some times after 10 records there may not be more records also
here api call is simple post request
api : https://xxxx.xxxx..com/<some method>
body: { "key1":"data1","key2":"data2","pageid":"ss"}
here in the first api call we wont send page id as after calling the first api call we will get response in that we will get the pageid and for the second api call i mean for paging then we have to use the pageid
For pagination you need to know total number of pages. Otherwise you need total number
of items along with number of items per page (to derive total number of pages). In your case
you only have a page-id which does not even say the which page you are on. The page-id
only gives you access to next page items.
This API is useful if you implement an infinite scroll feature. Otherwise you can only
implement a more button to which loads new items to table. The link
you provided in comments implements this more button feature.
So you can override the default footer of ngx-datatable to add your more button to load
more items to table.
<ngx-datatable-footer>
<ng-template ngx-datatable-footer-template
let-rowCount="rowCount"
let-pageSize="pageSize"
let-selectedCount="selectedCount"
let-curPage="curPage"
let-offset="offset"
let-isVisible="isVisible">
<div class="datatable-footer-inner selected-count">
<div class="page-count" *ngIf="selectedCount">
<span> {{selectedCount}} selected / </span> {{rowCount}} total
</div>
<div class="datatable-pager">
<ul class="pager">
<li class="pages active" role="button" aria-label="next" *ngIf="rowCount">
Next
</li>
</ul>
</div>
</div>
</ng-template>
</ngx-datatable-footer>
Stackblitz Demo
I got a postings template (Hogen.js) were I load data (api call from Laravel 5.3) into it.
I managed to load, compile and render the template and the data correctly.
Problem:
I have jquery/vanilla js scripts that need to work with the template and the data but somehow this JS is completely ignored by the rendered template and it doesn't work (onClick, other ajax calls etc.).
My load/render JS:
var $page = 1;
var source = $("#postTemplate").html();
var template = Hogan.compile(source);
$.ajax({
url: '/api/postings',
data: { page: $page} ,
type: 'POST',
success: function(data) {
var output = template.render(data);
$('.posts-container').prepend(output);
}
});
My Template:
<script id="postTemplate" type="text/x-hogan-template">
#{{#posts.data}}
<div class="post">
<div class="image">
<img src="#{{ imageURL }}" alt="post image" />
</div>
<div class="info">
<div class="like-count" data-like-id="#{{ id }}">
more html
</div>
</div>
#include('partials.comments')
</div>
#{{/posts.data}}
</script>
I include a partial from laravel with my "comment" code that needs to be execuded aswell (fadeIn, ajaxacalls,submit etc.)
Is it possible, that I cann ot execute my JS with the newly rendered template or DOM, because it's not available at document.ready?
Do I need to switch my template engine? Any other way to make this work?
JSON:
{
"success": true,
"posts": {
"total": 46,
"per_page": 20,
"current_page": 3,
"last_page": 3,
"next_page_url": null,
"prev_page_url": "http://localhost/api/postings?page=2",
"from": 41,
"to": 46,
"data": {
"40": {
"id": 6,
"name": " ",
"imageURL": "",
"city": "Spanien",
"country": "",
"created_at": "2018-03-11 09:40:25",
"profilePictureURL": null,
"social_src": 0,
"mediumImageURL": null
}
}
}
}
I stripped it down a bit!
You cannot use
#include('partials.comments')
in your hgan.js template. Hogan is (almost) logicless. It is for binding JSON to HTML templates, it is not capable or intended for this use.
Partials can only be used like folows:
var partialText = "normal text but can use {{foo}} is from a variable";
var p = Hogan.compile(partialText);
var text = "This template contains a partial ({{>partial}})."
var t = Hogan.compile(text);
var s = t.render({foo: chickens}, {partial: p});
is(s, "This template contains a partial (normal text but we can use chickens. is a variable).", "partials work");
Basically {{>partial}} can be used to nest another precompiled template.
I've seen so many ways to do this, but most are pretty old and I want to make sure I'm doing this correctly. Right now, the way I'm using isn't working and I feel like I'm missing something.
I'm getting the JSON back fine, I just need to get it to display in a table after I click the button.
Here is the JSON. This is how I'm going to get it from our server, I can't add any "var JSON =" or add any scope like "$scope.carrier" to the data, unless there's a way to add it after I've fetched the data.
{
"carrier":
[
{
"entity": "carrier",
"id": 1,
"parentEntity": "ORMS",
"value": "Medica"
}, {
"entity": "carrier",
"id": 2,
"parentEntity": "ORMS",
"value": "UHG"
}, {
"entity": "carrier",
"id": 3,
"parentEntity": "ORMS",
"value": "Optum"
}, {
"entity": "carrier",
"id": 4,
"parentEntity": "ORMS",
"value": "Insight"
}, {
"entity": "carrier",
"id": 5,
"parentEntity": "ORMS",
"value": "Insight"
}
]
}
Here is the app.js file to bring back the JSON data:
var app = angular.module('myTestApp', []);
app.controller('myController', ['$scope', '$http', function($scope, $http) {
var url = 'test.json';
$scope.clickButton = function() {
$http.get(url).success(function(data) {
console.log(data);
});
}
}]);
And then of course the HTML:
<div class="col-lg-12 text-center">
<button type=button class="btn btn-primary load" ng-click="clickButton()">Click!</button>
<table class="">
<tbody ng-repeat="carrier in carriers">
<tr>
<td>
<h3 class="">{{ module.entity }}</h3>
<h3 class="">{{ module.id }}</h3>
<h3 class="">{{ module.parentEntity }}</h3>
<h3 class="">{{ module.value }}</h3>
</td>
</tr>
</tbody>
</table>
</div>
I'm also wondering if I can use the ng-grid to put this in a table. I know they just upgraded it to ui grid so I'm not sure if this is still a feasible approach.
Also, I'm not getting errors, the data just won't display in the table right now. All I know is its returning the data properly, just not displaying in the table.
Any help is appreciated.
I looked at your plunker seems like you need to:
add angular script
wire the app and the controller
your variable in the repeater is wrong, I change it
take a look to this fixed plunker:
http://plnkr.co/edit/TAjnUCMOBxQTC6lNJL8j?p=preview
$scope.clickButton = function() {
$http.get(url).success(function(returnValue) {
alert(JSON.stringify(returnValue.carrier));
$scope.carriers = returnValue.carrier;
});
}
You never assign the value of the returned array to $scope.carriers.
At the line where you say console.log(data); add this:
$scope.carriers = data.data;
Here is the updated clickButton function (with a variable name change to reduce confusion):
$scope.clickButton = function() {
$http.get(url).success(function(returnValue) {
$scope.carriers = returnValue.data;
});
};