Knockout.js - Ideas on transforming JSON data to HTML - html

I have an observableArray self.CustomerOrders which I populate with
self.CustomerOrders.push(new CustomerOrder(self.getOrderId(), today.toLocaleDateString() , self.selectedCustomer2(), JSON.stringify(self.cart(),null,4)));
where
self.getOrderId() is a method to get an Id for the order,
today.toLocaleDateString() prints today's date,
self.selectedCustomer2 is the selected customer of the order and
self.cart is another observableArray which includes all ordered items.
Here is how I populate self.cart
self.cart.push(new orderedItem(product.id, product.name, product.price, product.quantity()));
and here is my foreach
<tbody data-bind="foreach: CustomerOrders">
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: date"></td>
<td data-bind="text: customer"></td>
<td data-bind="text: details"></td>
<td data-bind="click: $parent.selectedOrder"><a class="btn btn-primary" data-toggle="modal" data-target="#display-order">View</a>
</td>
<td data-bind="click: $parent.selectedOrder"><a class="btn btn-primary" data-toggle="modal" data-target="#edit-order">Edit</a>
</td>
<td data-bind="click: $parent.selectedOrder"><a class="btn btn-primary" data-toggle="modal" data-target="#delete-order">Delete</a>
</td>
</tr>
</tbody>
</table>
</div>
I succeed in saving all those data to the CustomersOrders observable array and then I print them in my UI using foreach. My problem is that the self.cart items are printed as JSON and I do not want to display JSON to the user but HTML.
How to implement this ?
Any ideas ?

Ok, so don't JSON.stringify your cart. Then, assuming your Details binding is where the cart part is supposed to end up, and it's supposed to be an array, you can just nest foreach bindings like this:
<td>
<ul data-bind="foreach: details">
<li data-bind="text: someProperty"></li>
</ul>
</td>
where someProperty is whatever property of the cart you want to display.
Of course, you can choose whatever html elements suit your requirements.

My problem is that the self.cart items are printed as JSON
Well, that's not surprising.
self.CustomerOrders.push(
new CustomerOrder(
self.getOrderId(),
today.toLocaleDateString(),
self.selectedCustomer2(),
JSON.stringify(self.cart(),null,4) /* guess what that does */
)
);
Just do
self.CustomerOrders.push(
new CustomerOrder(
self.getOrderId(),
today.toLocaleDateString(),
self.selectedCustomer2(),
self.cart
)
);
and use regular knockout bindings in your view to display the cart.

Related

Is there a simple way of using the th:data* and th:each attributes together in Thymeleaf?

My intention is to obtain an object inside one of the rows of the table, so I could forward it to a form using a simple JavaScript function. I am not familiar with jQuery so I thought I’ll take an as-simple-as-possible approach. I was thinking of doing this by using the th:data* attribute in combination with th:each, like this:
<tr th:each="employee : ${empDetailsList}" th:data-employee="${employee}">
<td scope="row" th:text="${employee.id}">ID</td>
<td scope="row" th:text="${employee.firstName}">firstName goes here</td>
<td scope="row" th:text="${employee.lastName}">lastName goes here</td>
<td scope="row" th:text="${employee.email}">email goes here</td>
<td scope="row" th:text="${employee.username}">user name goes here</td>
<td th:data-employee="${employee}">
<button type="button" class="btn btn-info" th:onclick="showEditForm(this.getAttribute('data-employee'));">Details</button>
</tr>
I also tried this approach, moving the th:data-employee from the 'tr' tag to the 'td' tag but the result is the same:
<tr th:each="employee : ${empDetailsList}">
...
<td th:data-employee="${employee}">
<button type="button" class="btn btn-info" th:onclick="showEditForm(this.getAttribute('data-employee'));">Details</button>
</tr>
The JS function:
function showEditForm(employee){
console.log('Employee object here: ');
console.log(employee.firstName);
console.log(employee.lastName);
}
As I mentioned I get the same result in both cases. The browser consoles response is:
Employee object here:
TypeError: employee is null
So, what am I doing wrong here?
This worked for me:
<p th:each="testScript:${testScripts}">
<a th:href="|/scripts/start/${testScript}|" th:text="'Start '+ ${testScript}"/>
<a th:href="|/scripts/stop/${testScript}|" th:text="'Stop' + ${testScript}"/>
<button id="searchButton" name="searchButton" th:onclick="start(this.getAttribute('data_p1'));" type="button"
th:data_p1="|${testScript}|"
th:text="|${testScript}|">Start</button>
</p>

HTML Partial View within Foreach

My index views in MVC contain a row per row set of actions like so:
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.SomeProperty)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.ID" class="btn btn-warning" style="margin-top: -8px">
<span class="fa fa-pencil" alt="Edit" />
</a>
<a asp-action="Details" asp-route-id="#item.ID" class="btn btn-primary" style="margin-top: -8px">
<span class="fa fa-info-circle" alt="Details" />
</a>
<a asp-action="Delete" asp-route-id="#item.ID" class="btn btn-danger" style="margin-top: -8px">
<span class="fa fa--trash" alt="Delete" />
</a>
</td>
</td>
}
There are other index pages where the 3 buttons will get reused so that already suggests a partial view just to save redundant code, the other part is I have to have the alt tag in the spans for 508 compliance so I want a partial view to help with consistency.
Problem is, if I just copy and paste the 3 buttons into a partial view, then I get "The name 'item' does not exist in the current context" and if I try to bring over the foreach, then I get more then one set of buttons in each row. Any ideas?
What I believe is that your problem is related to the model which you didn't pass to the partial. There are some ways that you can pass your model to the partial view.
Think you have an Index view which has a model:
#model YourProjectNameSpace.Models.NameOfModel
......//Other HTML codes
when you want to call the partial view inside this view you should pass the model:
#Html.Partial("_MyPartial",Model)
Also inside of your partial view, you need to add the following line in the beginning:
#model YourProjectNameSpace.Models.NameOfModel

show a string from backend-server as icon

I get a response from backend server for my angular 2/4 application. The response includes an attribute "connectionStatus", which indicates the status of a database-connection with "UP" or "DOWN". I show the retrieved status and other informations in my view with the following code:
<tbody>
<tr *ngFor='let database of environment.databases'>
<td>{{database.connectionName}}</td>
<td>{{database.dbSourceType}}</td>
<td>{{database.username}}</td>
<td>{{database.password}}</td>
<td>{{database.connectionUrl}}</td>
<td>{{database.creationDate}}</td>
<td>{{database.connectionStatus}}</td>
<td>
<button (click)='onEditDatabase(environment,database)'class="btn btn-primary btn-sm oi oi-cog"></button>
<button (click)='onDeleteDatabase(database)'class="btn btn-danger btn-sm oi oi-trash"></button>
</td>
</tr>
</tbody>
Instead of showing the status as "UP" or "DOWN", i want to use openiconics. If the state is "UP", then use the check-icon, if its down, the flash-icon. How can i realize that? i appreciate all help.
Make use of ngClass
<td [ngClass]="(database.connectionStatus ==='UP')?'upclass':'downclass'"></td>
in the css define the class and icons
.upclass{check-icon}
.downclass{flash-icon}
You can use *ngIf or [hidden] to display one of the status as per your condition.
<td *ngIf="database.connectionStatus">your icon UP html tag here</td>
<td *ngIf="!database.connectionStatus">your icon DOWN html tag here</td>

Angular 2 save all changes from grid

I need to save all changes from editable fields in table.
<tbody>
<tr *ngFor="let a of arr; let i = index">
<td contenteditable>{{a.text}}</td>
<td contenteditable type="number" pattern="[0-9]">{{a.number}}</td>
</tr>
</tbody>
<button class="btn btn-success" (click) = "saveAllChanges()">Save all </button>
--
saveAllChanges(){
for(let a of this.arr){
this.myservice.updateRepeat(r)
}
}
Objects in array arent saved after edit on grid so it doesnt work.
Any idea how can i save all changes?

*ngIf=item.activityStatus!=("Done") as angular2 conditional visibility

I want to toggle the visibility of a button based of a value of an item
Here is my code:
<tbody>
<tr *ngFor="let item of statusConfig | slice:0:9; let i = index;" >
<td class="col-md-1">
{{item.id}}
</td>
<td class="col-md-3">
{{item.activityName}}
</td>
<td class="col-md-2">
{{item.activityStatus}}
</td>
<td class="col-md-3">
{{item.activityDateEpoch | date: 'yyyy-MM-dd HH:mm:ss'}}
</td>
<td class="col-md-3">
<button *ngIf=item.activityStatus!=("Done") type="button" class="btn btn-primary" (click)="saveStatus(item.id, i)">Mark as done</button>
</td>
</tr>
</tbody>
why is this a syntax error and how should I fix this?
directive_normalizer.js:82 Uncaught Error: Template parse errors:
Unexpected closing tag "button" ("tyStatus!="Done" type="button" class="btn btn-primary" (click)="saveStatus(item.id, i)">Mark as done[ERROR ->]</button>
</td>
"): ReportComponent#45:145
and
activityStatus = "Done" for now
I'm in shock how many mistakes you managed to make in one line of code. :-)
First: NgIf directive accepts string as expression value, which means it has to have the following form:
*ngIf="expression here"
Second: You can't use " two times, if you want to use string in ", you should use single quotes then (')
Third: Brackets are not needed: ("Done")
Anyway, your expression should look like this:
*ngIf="item.activityStatus != 'Done'"
You can read more about NgIf directive here.
It should be,
*ngIf="(item.activityStatus!='Done')"