I have an model in which I have a method is valid
export class ModelClass{
id: number;
text : String,
isValid() : boolean {
return true;
}
}
a second model
export class Rows{
editable: boolean;
modelClass: ModelClass;
}
how to call it in html ???
<table border="1p;">
<tbody >
<tr *ngFor="let link of modelClassRows">
<td>
<div>toto {{link.applicationLink.isValid()}}</div>
</td>
</tr>
</tbody>
</table>
a part of my component where object are initialized
export class ApplicationLinkListComponent implements OnInit {
modelClassRows: Rows[] = new Array<Rows>();
constructor() {
}
ngOnInit() {
// fill modelClassRows
.....
}
You need to instantiate the ModelClass class this way:
let row = new Rows();
row.modelClass = new ModelClass();
row.modelClass.id = 'some id';
row.modelClass.title = 'some title';
modelClassRows.push(row);
If you instantiate it literally and cast it to the type, you won't be able to use the method.
For example:
let row = new Rows();
row.modelClass = <ModelClass>{
id: 'some id',
title: 'some title'
};
modelClassRows.push(row);
Related
I am new to ag-grid with Angular. I have simple html table to list users. And i want to use ag-grid for this. There are few columns which shouldn't be displayed if there is no permission. I am not sure how to achieve this using ag-grid. Can anyone please help me how to achieve this?
Existing html table:
<table>
<thead>
<tr>
<th width="30"> </th>
<th>Name</th>
<ng-container *requireAnyPermission="[SensitiveAccessPermission]">
<th>Modified by</th>
<th>Modified date</th>
</ng-container>
<th *requireAnyPermission="[SensitiveAccessPermission]">Active</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let person of people">
<td> </td>
<td data-label="Name">{{ person.name }}</td>
<ng-container *requireAnyPermission="[SensitiveAccessPermission]">
<td data-label="Modified by">{{ person.modifiedBy }}</td>
<td data-label="Modified date">
{{ person.modified | dateTimeFormat }}
</td>
</ng-container>
<td *requireAnyPermission="[SensitiveAccessPermission]" data-label="Active">
<ng-container *ngIf="person.isActive; then checkTemplate"></ng-container>
</td>
</tr>
</tbody>
</table>
I have the ag-grid column definition as below:
const COLUMNS: ColDef[] = [
{ headerName: '', field: '' },
{ headerName: 'Name', field: 'name', filter: true },
{ headerName: 'Modified by', field: 'modifiedBy', filter: true },
{ headerName: 'Modified date', field: 'modified', filter: true },
{ headerName: 'Active', field: 'isActive', filter: true },
];
How to achieve the same with ag-grid.
*requireAnyPermission is custom directive
#Directive({
// tslint:disable-next-line: directive-selector
selector: '[requireAnyPermission]'
})
export class RequireAnyPermissionDirective implements OnDestroy {
private _onDestroy = new Subject();
private _reverse = false;
private _anyPermissions: Array<string | PermissionCodeWithMask>;
#Input() set requireAnyPermission(
permissions: Array<string | PermissionCodeWithMask>
) {
this._anyPermissions = permissions;
this.updateView();
}
#Input() set requireAnyPermissionReverse(reverse: boolean) {
this._reverse = reverse;
this.updateView();
}
constructor(
private templateRef: TemplateRef<HTMLElement>,
private viewContainerRef: ViewContainerRef,
private userService: UserService
) {}
ngOnDestroy(): void {
this._onDestroy.next();
}
private updateView() {
if (this._anyPermissions) {
this.userService
.userHasAnyPermissions(this._anyPermissions)
.pipe(takeUntil(this._onDestroy))
.subscribe((hasPermission) => {
this.viewContainerRef.clear();
if (
(hasPermission && !this._reverse) ||
(!hasPermission && this._reverse)
) {
this.viewContainerRef.createEmbeddedView(this.templateRef);
}
});
}
}
}
Thanks
You can do that by either constructing the column definitions array programmatically based on the permissions the user have OR remove the columns you want to hide from COLUMNS on component initialization
In both cases you would have to call
gridOptions.api.setColumnDefs(columnDefs);
after you are done
Look at updating column defs example here
You wanna do something similar.
You can show/hide columns:-
this.gridColumnApi.setColumnsVisible([...visibleCols], true); // show columns
this.gridColumnApi.setColumnsVisible([...hiddenCols], false); // hide columns
If you want those column, not available in the grid:-
when creating columnDefs for grid, dont add in columnDefs conditionally
In my opinion this is simple method (* For Big Project and multiple change)
First get all column list for grid like.
getKeys(obj: []) {
var keys = [];
for (var key in obj) {
keys.push(key);
}
return keys;
}
this getKeys method give you all ColumnName of over array
//item is json response from over server.
var columns = this.getKeys(item[0]);
var colObj = {};
var gridcolumnDefs = [];
for (var i = 0; i & lt; columns.length; i++) {
var visible = true;
switch (columns[i].toLocaleLowerCase()) {
case 'columnname1':
colObj = {
field: columns[i],
sortable: false
}
break;
case 'columnname2':
visible = false;
colObj = {
field: columns[i],
sortable: false
}
break;
default:
break;
}
if (visible) {
if (colObj != undefined)
this.gridcolumnDefs.push(colObj);
}
}
// set column grid
this.GridName.setColumnDefs(this.gridcolumnDefs)
please try and check.
I have a Apex method which returns the list of wrapper class as JSON string
having LWC js controller to call the method in connnectedCallback() and the wrapper list is assigned to a property this.coreAttributes which is show in html page using basic html tags along with other property defined in LWC noOfBlocks, faltHierarchy, and one more. code given below.
When I enter some value in coreAttribute's related input filed and enter some value in noOfBlocks input field, the value entered in the coreAttribute related fields are gone. please check the attached gif and help me to resolve this.
Image : https://easyupload.io/g1h772
#AuraEnabled(cacheable=true)
public static String queryCoreAttributes() {
List<Core_Attribute__c> coreAttributesList = new List<Core_Attribute__c>();
Map<Id,List<String>> picklistValuesToPicklistMasterMap = new Map<Id,List<String>>();
coreAttributesList = [SELECT Id, Name, Data_Type__c, Type__c, Picklist_Master__c
FROM Core_Attribute__c WHERE Base_Asset_Name__c IN (SELECT Id FROM Base_Asset_Template__c WHERE Name = 'Base PV Plant')
ORDER BY Name ASC];
picklistValuesToPicklistMasterMap = Utils.getPicklistValues();
System.debug(' picklistValuesToPicklistMasterMap '+ picklistValuesToPicklistMasterMap);
List<coreAttributesWrapper> coreAttributesWrapperList = new List<coreAttributesWrapper>();
for(Core_Attribute__c coreAttribute : coreAttributesList){
coreAttributesWrapper coreAttWrapper = new coreAttributesWrapper();
coreAttWrapper.attributeHeader = coreAttribute.Name;
coreAttWrapper.attributeDataType = coreAttribute.Data_Type__c.toLowerCase();
coreAttWrapper.picklistValues = (coreAttribute.Data_Type__c == 'Picklist') ? picklistValuesToPicklistMasterMap.get(coreAttribute.Picklist_Master__c): null;
coreAttWrapper.isPicklist = (coreAttribute.Data_Type__c == 'Picklist');
coreAttWrapper.attributeValue = '';
coreAttributesWrapperList.add(coreAttWrapper);
}
System.debug(' core Att '+ coreAttributesWrapperList);
return JSON.serialize(coreAttributesWrapperList);
}
JS
import { LightningElement, track, api } from "lwc";
import getPlantAssetRecord from "#salesforce/apex/P1PlantInfoPromptSolar.queryPlantAssetRecord";
import queryCoreAttributes from "#salesforce/apex/P1PlantInfoPromptSolar.queryCoreAttributes";
import saveP1PlantInfoPromptMetadata from "#salesforce/apex/P1PlantInfoPromptSolar.saveP1PlantInfoPromptMetadata";
export default class P1PlantInfoPromptSolar extends LightningElement {
#api plantAssetId='';
#track plantAssetDetail;
#track coreAttributes;
#track noOfBlocks='';
#track flatHierarchy=false;
#track drivePlus=false;
#track promptSpecificAttributes;
connectedCallback() {
console.log(' connected callback ');
getPlantAssetRecord({
recordId: 'a060p000001hGLxAAM',
})
.then(result => {
this.plantAssetDetail = result;
})
.catch(error => {
this.error = error;
});
queryCoreAttributes()
.then(result => {
console.log(' result ' + result);
console.log(' JSON result ' + JSON.parse(result));
this.coreAttributes = JSON.parse(result);
})
.catch(error => {
this.error = error;
});
}
inputTagValueChangeHandler(event){
console.log(' test '+ JSON.stringify(this.coreAttributes));
console.log(' value -> '+ event.target.value + ' name -> ' + event.target.name);
if(event.target.name === 'Blocks') this.noOfBlocks = event.target.value;
if(event.target.name === 'Flat Hierarchy') this.flatHierarchy = event.target.value;
if(event.target.name === 'Drive+') this.drivePlus = event.target.value;
}
HTML
<tr data-row="1">
<th># Blocks</th>
<td><input type="number" name="Blocks"
value={noOfBlocks} onchange={inputTagValueChangeHandler}/></td>
</tr>
<tr data-row="2">
<th>Flat Hierarchy</th>
<td><input type="checkbox" name="Flat Hierarchy"
value={flatHierarchy} onchange={inputTagValueChangeHandler}/></td>
</tr>
<tr data-row="2">
<th>Drive+</th>
<td><input type="checkbox" name="Drive+"
value={drivePlus} onchange={inputTagValueChangeHandler}/></td>
</tr>
<template for:each={coreAttributes} for:item="coreAttribute">
<tr key={coreAttribute.key}>
<th>{coreAttribute.attributeHeader}</th>
<td>
<template if:false={coreAttribute.isPicklist}>
<input type={coreAttribute.attributeDataType} name={coreAttribute.attributeHeader}
value={coreAttribute.attributeValue}/>
</template>
<template if:true={coreAttribute.isPicklist}>
<select size="1" name={coreAttribute.attributeHeader}>
<option value="None">--None--</option>
<template for:each={coreAttribute.picklistValues} for:item="attributePickValues">
<option key={coreAttribute.key} value={coreAttribute.attributeValue}>{attributePickValues}</option>
</template>
</select>
</template>
</td>
</tr>
</template>
I'm using this video-example (https://www.youtube.com/watch?v=FZSjvWtUxYk) in order to make an errors reporting app. The problem comes when in the View when it passes the object that comes from the REST-AJAX call, _.template says that errores is not defined.
Here is my code:
var Error = Backbone.Model.extend({
defaults: {
iderror: '',
title: '',
url: ''
},
idAttribute: 'iderror'
});
var Errores = Backbone.Collection.extend({
model: Error,
url: '/errores'
});
var ErrorList = Backbone.View.extend({
el: '.page',
render: function (eventName) {
var that = this;
var errores = new Errores();
errores.fetch({
success: function (errores) {
var template = _.template($('#error-list-template').html(),{errores: errores.models});
that.$el.html(template);
}
});
}
});
My Template code:
<script type="text/template" id="error-list-template">
Registrar Error
<hr/>
<table class="table striped">
<thead>
<tr>
<th>Id Error</th>
<th>TÃtulo</th>
<th>URL</th>
<th></th>
</tr>
</thead>
<tbody>
<%
_.each(errores, function(error) { %>
<tr>
<td><%= error.get('iderror') %></td>
<td><%= error.get('title') %></td>
<td><%= error.get('url') %></td>
<td>Editar</td>
</tr>
<% }); %>
</tbody>
</table>
</script>
My RESTful GET function made with SLIM Framework:
$app->get('/errores/', function () {
//echo "Hello, ";
$datos = array();
$db = NewADOConnection('mysqli');
$db->Connect("localhost", "root", "mypassword", "tt1r");
$sql = "SELECT * FROM tt1r.course";
$qry = $db->execute($sql);
/*while (!$qry->EOF) {
//print_r($qry->fields);
$datos = [$qry->iderror => ['title' => $qry->title, 'url' => $qry->url]];
$qry->MoveNext();
}*/
if($qry) {
foreach($qry as $re){
//return $re['ADM_ID'];
$datos[] = array("iderror" => $re['iderror'],"title" => $re['title'],"url" => $re['url']);
}
$db = null;
//echo json_encode($datos);
//echo '{"user": ' . json_encode($datos) . '}';
echo json_encode($datos);
}
});
I have to say that I do get the JSON array with the data from the RESTful function, but it doesn't show it.
Thank you for your help.
Best regards.
Rafa
I read the answer in a post made by RyanP13.
So the fixed View code is:
var ErrorList = Backbone.View.extend({
el: '.page',
render: function () {
var that = this;
var errores = new Errores();
errores.fetch({
success: function(errores, response, options){
var template = _.template($('#error-list-template').html());
that.$el.html(template({ errores: errores.toJSON()}));
}
});
}
});
The problem was that I did not had any reference from the Collection.
Hope this help you as well.
Best regards
Rafa
i'm having a problem with the delete operation using KOjs and EF6.when i click the remove button the confirmation dialog appears but the selected row is not deleted.
This is my controler:
public JsonResult FetchActivities()
{
return Json(_account.FindAllActivities(), JsonRequestBehavior.AllowGet);
}
[System.Web.Mvc.HttpDelete]
public void DeleteActivity(int id)
{
try
{
if (id != 0)
{
_account.Delete(id);
}
}
catch
{
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
}
and this is the view:
<table class="table table-striped table-bordered table-condensed">
<tr>
<th>URL</th>
<th>Thumbnail</th>
<th>Title</th>
</tr>
<tbody data-bind="foreach: Activities">
<tr>
<td data-bind="text: urlactivite"></td>
<td data-bind="text: thumbnail"></td>
<td data-bind="text: title"></td>
<td><button class="btn btn-mini btn-danger" data-bind="click: $parent.removeActivity">remove</button></td>
</tr>
</tbody>
and here is the view model:
var ProfilesViewModel = function () {
var self = this;
var url = "/WhiteList/FetchActivities";
var refresh = function () {
$.getJSON(url, {}, function (data) {
self.Activities(data);
});
};
// Public data properties
self.Activities = ko.observableArray([]);
self.removeActivity = function (profile) {
if (confirm("Are you sure you want to delete this profile?")) {
var id = profile.id;
waitingDialog({});
$.ajax({
type: 'DELETE', url: '/WhiteList/DeleteActivity/' + id,
success: function () { self.Activities.remove(profile); },
error: function (err) {
var error = JSON.parse(err.responseText);
$("<div></div>").html(error.Message).dialog({ modal: true, title: "Error", buttons: { "Ok": function () { $(this).dialog("close"); } } }).show();
},
complete: function () { closeWaitingDialog(); }
});
}
};
refresh();
};
ko.applyBindings(new ProfilesViewModel());
I see no errors in my code.Can any one help me
Your code has several mistakes:
the only observable property is the Activities observable array: when you load the data with refresh() you are creating an observable array of regular, non-observable, objects. That means that ypu are trying to make bindings between the regular, non-observable properties of your array and your activities.
you're not passing any parameter to your removeActivity, and you are expecting to get a profile (what is that) and get it's id to delete it.
You'd need to make modifications to your model:
Create an Activity constructor with the same properties of the activity, but declared as observable properties
One of these 2 options
Include the removeActivity in the Activity constructor, to get the id of the activity to remove using this (or self)
Include removeActivity in the root for your model, and recive the id as parameter, and pass the id of the activity in the click binding
Modify refresh so that you map each element of the received activities to a new Activity object created with your constructor
If you choose option 2.2 you can make it automatically using knockout mapping.
Please, look at your code and try to see why you expected to receive a profile in removeACtivity function. I suppose you'll understand it made no sense.
I have a situation where I need to edit an enumerable property in a view model:
public class ViewModel
{
public MyObj Obj { get; set; }
public IEnumerable<MyObj> MyObjs = new List<MyObj>();
}
I have followed this post; controller action:
public ActionResult Index()
{
var viewModel = new ViewModel();
viewModel.Obj = new Obj() { Name = "0", Value = true };
var o1 = new MyObj() { Name = "1", Value = false };
var o2 = new MyObj() { Name = "2", Value = false };
viewModel.Objs = new List<Obj>() { o1, o2 };
return View(viewModel);
}
[HttpPost]
public ActionResult Index(ViewModel viewModel)
{
return View(viewModel);
}
The Index view as follows:
<% using (Html.BeginForm()) { %>
<table>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<%= Html.EditorFor(x => x.Objs) %>
</table>
<br />
<input type="submit" value="Submit" />
<% } %>
And the editor template in "~/Views/Home/EditorTemplates/Obj.ascx":
<tr>
<td><%: Html.TextBoxFor(x => x.Name) %></td>
<td><%: Html.CheckBoxFor(x => x.Value) %></td>
</tr>
The issue is: browse to Index, the data shows up. The POST, and the enumerable data disappears. Stepping through, the singular "Obj" in the view model remains, so it is just the enumerable data that is disappearing.
I have been staring at this for some time now, if any one could help out it would be brilliant.
Cheers,
Tim.
Take a look at this post by Phil Haack, MVC2 doesn't natively support binding a list back to the viewmodel unless you do a little manipulation.
Update: I've looked into this a little more and think you should try adding TryUpdateModel(viewModel.MyObjs, "MyObjs"); to your Controller. This informs the modelbinder that it should use the "MyObjs" binding prefix to attach the data from the form to the collection in your ViewModel.