How to convert indexed Json to normal Json array in Angular 7 - angular7

I get the data from API end point as below
But the output I expect is just an array of object which is like
[{Crqnumber: "CRQ000000135318",
approvalstatus: "Approved",
changecoordinator: "Sariga Suresh",
productname: "MSS (NextGen)",
status: "Closed",
statusreason: "Successful"},
{Crqnumber: "CRQ000000135318",
approvalstatus: "Approved",
changecoordinator: "Sariga Suresh",
productname: "MSS (NextGen)",
status: "Closed",
statusreason: "Successful"},
{Crqnumber: "CRQ000000135318",
approvalstatus: "Approved",
changecoordinator: "Sariga Suresh",
productname: "MSS (NextGen)",
status: "Closed",
statusreason: "Successful"}]
I decide to use pipe() and map() for achieving this, but I am stuck. I could not achieve the expected out.
my service is
export class CrqData{
constructor(private http: HttpClient){}
getCrqList(){
return this.http.get<Crq[]>('http://d7598:8000/crqlist/').pipe(map((responseData=>{
let temp: Crq[]=[];
temp=responseData;
return temp
})));
}
}
my component ts file
export class CrqComponent implements OnInit {
crqList = [];
constructor(private crqData:CrqData) {
this.crqData.getCrqList().subscribe((data)=>{
console.log(data)
}, (error)=>{
console.log(error);
});
}
ngOnInit() {
}
}
my component html
<mat-card style="padding: 1.5%; margin: 1%;" *ngFor="let crq of crqList">
<mat-card-content>
<div style="line-height: 20px;">
<div style="float: left; font-weight: bold;">
<p>CRQ No: {{crq.Crqnumber}}</p>
</div>
<div style="float: right; font-weight: bold;">
<p style="float: left;padding-top: 1px;">
<i class="material-icons" style="font-size: 12px;">fiber_manual_record</i>
</p>
<p style="float: right;">{{crq.approvalstatus}}</p>
</div>
</div>
<div style="clear: both; line-height: 6px; font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;">
<p style="text-align: left;">Change coordinator: {{crq.changecoordinator}}</p>
<p style="text-align: left;">Title: {{crq.productname}}</p>
</div>
</mat-card-content>
</mat-card>
my object is
export interface Crq{
Crqnumber: string;
approvalstatus: string;
changecoordinator: string;
productname: string;
status: string;
statusreason: string;
}

First of all, you should change your type in the http.get call. You're not recieving a Crq[], you're receiving an object which contains 3 properties, where one property (results) is of the type Crq[].
So you should define a type which holds all these 3 properties, like this: (you can put this above the line export class CrqData {)
interface CrqResponse {
count: number;
error: number;
results: Crq[];
}
Now, you can use this in your http request and use the response, like this:
getCrqList(){
return this.http.get<CrqResponse>('http://d7598:8000/crqlist/').pipe(map((responseData=>{
return responseData.response;
})));
}
I'd also suggest that you throw an error if the error property is not equal to 0, so that instances that use your service can catch the error if there is one. So getCrqList() should look something like this:
getCrqList() {
return this.http.get<CrqResponse>('http://d7598:8000/crqlist/').pipe(switchMap((responseData=>{
if(responseData.error !== 0) {
return throwError(responseData.error);
}
else {
return of(responseData.response);
}
})));

I think you have to get results property from the response so you have to modify this method to be like this
export class CrqData{
constructor(private http: HttpClient){}
getCrqList(){
return this.http.get<Crq[]>('http://d7598:8000/crqlist/').pipe(map((responseData=>{
const { results } =responseData;
return results
})));
}
}

I found the answer. I should have my service class as below
export class CrqData{
constructor(private http: HttpClient){}
getCrqList(){
return this.http.get<Crq[]>('http://d7598:8000/crqlist/').pipe(map((responseData=>{
let temp: Crq[]=[];
for(let data in responseData){
for(let d in responseData[data]){
console.log(responseData[data][d]);
temp.push(responseData[data][d]);
}
}
return temp
})));
}
}

Related

Why does the iOS content go up when a element is added?

I'm using Ionic to build a chat app, but I'm facing a problem, when I run my app on the iOS environment, every time a new message is added to the content the content goes up without any reason.
I've tried everything but I still didn't find a way to fix it, note that this bug only appears with the iOS content but works perfectly on Android.
I've published a video to show this bug
here is the code that I'm using to update the messages
ngOnInit() {
this.chatID = this.route.snapshot.paramMap.get('id');
this.afs
.collection(`chat/${this.chatID}/messages`,(ref) => ref.orderBy('createdAt'))
.valueChanges({ idField: 'id' })
.subscribe((event) => {
this.data = event;
console.log(this.data);
});
}
This is the function to push the new message
addChatMessage() {
const { newMsg } = this;
this.chatID = this.route.snapshot.paramMap.get('id');
this.afs
.collection(`chat/${this.chatID}/messages`)
.add({
msg: newMsg,
profilePic: this.profilePic,
username: this.username,
from: this.user.getUID(),
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
})
this.newMsg = '';
}
And here is the HTML code
<div *ngFor="let message of data">
<div style="display: flex; justify-content: flex-end">
<div style=" display: flex;
flex-direction: column;
align-items: flex-end;
">
<ion-card class="my-message"
*ngIf="message.username == username">
<ion-label>
{{ message.msg }}
<br />
</ion-label>
</ion-card>
</div>
</div>

Vapor 3 Rendering leaf template with script inline

I am trying to render a template in Vapor 3 with Leaf. Most of my HTML is in my base.leaf. In the login.leaf template, I need to add a JS script. Trouble is when it gets to the function it breaks and renders the function. Can anyone tell me how to add these properly? Thanks for your help in advance. Here's what is giving me problems:
#set("content") {
<h1>#(title)</h1>
<div id="logo"><img src="images/global/journey_trax_logo.png" alt=""/></div>
<div id="sheet1" class="form_sheet">
<input type="text" class="text_input" id="name_field" placeholder="NAME">
<input type="password" class="text_input" id="password_field" placeholder="PASSWORD">
<div id="continue_btn1" class="text_btn" onClick="logIn();">Continue</div>
<p> </p>
</div>
<script>
var user_name = readCookie("user_name");
var user_password = readCookie("user_password");
document.getElementById("user_name").value = user_name;
document.getElementById("user_password").value = user_password;
function logIn() {
var baseURL = window.top.location.href;
if (baseURL.indexOf("#") != -1) {
baseURL = window.location.href.split("#")[0];
}
var url = baseURL + "login";
console.log("[logIn] post to URL: "+url);
console.log("[logIn] name: "+user_name+", password: "+user_password);
$.post( url,
{
name: user_name,
password: user_password
},
function(data) {
// Do something with the return data?
console.log("[logIn] callback data: "+data);
console.log("[logIn] handle succes or error");
//
parent.loadHTML('screens/home.html');
}
);
}
</script>
<style>
.text_input, select {
width: 100%;
margin-bottom: 30px;
}
.text_btn {
width: 100%;
margin-top: 20px;
cursor: pointer;
}
</style>
}
#embed("base")
Your fundamental problem is that the } characters in the Javascript are being captured by Leaf because it is inside the #set tag. You have two choices:
Leave it where it is escape all the instances of } inside your <script> tag to \}. As far as I can tell, it doesn't need { escaping in the same way; presumably, this is because there isn't a Leaf tag immediately preceding. This works reliably and you can use Leaf to generate your javascript server-side before sending it to the client.
Move the <script> and contents above (i.e. outside) the #set tag. If you do embed any Leaf tags inside the javascript, you'll need to start escaping any } characters belonging to the Javascript as option 1.

asp.net core page not found

I have error "Page not found" on my website.
This is what i have came up with.
Error occurred to clients few times without me knowing exact moment
When i tested it it ALWAYS happens when i restart my website asp.net server but under some circumstances which i will describe later
It happens in some controllers but in some not
It happens only until i open some controller that will load website, then all other works too.
It happens only on published website and not in my local environment.
So first line is clear and doesn't need explanation.
Second line:
What i have tested to get this error is i shut down my server and then start it again. After it i try going to mywebsite.com/User and error comes.
Third line:
It only happens in controllers /User and /Kalkulator but not in / or /Proizvodi
Forth line:
When i open controller /User and refresh it multiple times it doesn't load but when i go to / and then to /User it loads.
Here are my controllers with their views. I will only provide /User and /Kalkulator since there is easiest to see what happens.
public class UserController : Controller
{
public IActionResult Index()
{
//Debug log are control lines that write to my txt file but they are never reached on first time going to this controller, but when i do fourth step they do reach.
Debug.Log(null, "User/Index pocetak", Debug.Type.CasualChange, Request);
try
{
Debug.Log(null, "User/Index Checking isLogged", Debug.Type.CasualChange, Request);
if (Networking.IsLogged(Request))
{
Debug.Log(null, "User/Index Checking isAdmin", Debug.Type.CasualChange, Request);
if (Networking.IsAdmin(Request))
{
Debug.Log(null, "User/Index Return redirect admin", Debug.Type.CasualChange, Request);
return Redirect("/Admin?select=POR");
}
else
{
Debug.Log(null, "User/Index Return redirect /Proizvodi", Debug.Type.CasualChange, Request);
return Redirect("/Proizvodi");
}
}
Debug.Log(null, "User/Index Creting new user class", Debug.Type.CasualChange, Request);
AR.TDShop.User u = new AR.TDShop.User();
Debug.Log(null, "User/Index Return view with user class", Debug.Type.CasualChange, Request);
return View(u);
}
catch (Exception ex)
{
Debug.Log(null, "User/Index catch error", Debug.Type.CasualChange, Request);
return View("Error", ex.ToString());
}
}
User View
#model AR.TDShop.User
#{
ViewData["Title"] = "Profi kutak";
}
<style>
#Login {
margin: auto;
position: relative;
width: 400px;
text-align: center;
margin-top: 100px;
border-radius: 10px;
border: 1px solid red;
}
#Login input {
margin-top: 10px;
text-align: center;
height: 40px;
font-size: 30px;
width: 60%;
}
#Login button {
margin-top: 20px;
margin-bottom: 20px;
width: 200px;
height: 40px;
font-size: 18px;
border: none;
background-color: #ff0000;
border-radius: 0px 0px 20px 20px;
color: white;
font-weight: bolder;
}
#Login button:hover {
background-color: #ff4d4d;
}
#PostaniClan button:hover {
background-color: lawngreen !important;
color: black !important;
}
</style>
#using (Html.BeginForm("Login", "User", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div id="Login">
<p style="padding-top: 10px; padding-bottom: 10px; border-radius: 10px 10px 0 0; color: white; background-color: red; font-weight: bolder; font-size: x-large">Logovanje</p>
#Html.TextBoxFor(x => x.Name, new { #placeholder = "username" })
<br />
#Html.TextBoxFor(x => x.PW, new { #placeholder = "password", #type = "password" })
<br />
<button type="submit">Potvrdi</button>
</div>
}
<div style="text-align: center; margin-top: 30px; margin-bottom: 30px" id="PostaniClan">
<button onclick="window.location.href='/Majstori/Registracija'" style="background-color: green; color: white; border-radius: 20px; padding: 10px 20px 10px 20px;">Postani član!</button>
</div>
}
As you can see in user controller/view there are few other commands that are not shown here but i think you do not need them and you will get it when you take a look at /Kalkulator controller which also doesn't works and here it is:
public class KalkulatorController : Controller
{
public IActionResult Index()
{
return View();
}
}
and here is the view:
#{
ViewData["Title"] = "Kalkulator";
}
<div class="main-wrapper">
<div class="card bg-info text-center" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">GKP - Plafon</h5>
<p class="card-text">Izracunajte utrosak materijala koji Vam je potreban za izradu spustenog plafona u gips karton sistemu.</p>
Izracunaj!
</div>
</div>
<div class="card bg-info text-center" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">GKP - Zid (oblaganje)</h5>
<p class="card-text">Izracunajte utrosak materijala koji Vam je potreban za oblaganje postojeceg zida.</p>
Izracunaj!
</div>
</div>
<div class="card bg-info text-center" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">GKP - Zid (pregradjivanje)</h5>
<p class="card-text">Izracunajte utrosak materijala koji Vam je potreban za izradu novog pregradnog zida.</p>
Izracunaj!
</div>
</div>
</div>
As you can see it is pure HTML and it doesn't work....
Here is my /Proizvodi controller which works (it has a lot of commands so i will display only index and view)
public IActionResult Index(int? GrupaID, int? PodgrupaID, int? V, string Pretraga)
{
ProizvodiModel pm = new ProizvodiModel(GrupaID, PodgrupaID, V, Request);
pm.Tag = Pretraga;
return View(pm);
}
VIEW:
#model ProizvodiModel
#{
ViewData["Title"] = "Proizvodi";
List<Tuple<int, double>> CeneZaKorisnika = new List<Tuple<int, double>>();
if (Networking.IsLogged(Context.Request))
{
CeneZaKorisnika = AR.TDShop.User.GetVPCene(Model.User.UserID);
CeneZaKorisnika.Sort((x, y) => x.Item1.CompareTo(y.Item1));
}
if (!Model.Majstor)
{
<style>
.proizvod {
margin-bottom: 5px !important;
}
</style>
}
else
{
<style>
.proizvod {
margin-bottom: 103px !important;
}
</style>
}
}
<link rel="stylesheet" type="text/css" href="~/css/ProizvodiIndex.css" />
<div class="main-wrapper">
<div id="left" class="col-sm-3" style=" color: white">
<div style="width: 100%; margin-top: 40px; margin-bottom: 40px; text-align: center">
<img src="~/images/Logo_Long.png" style="width: 90%;" />
</div>
#if (Model.Majstor)
{
Model.User.UcitajPorudzbine(Context.Request);
if (Model.User.Porudzbine.Count > 0)
{
<div style="background-color: red; margin-top: 10px; padding-top: 10px; padding-bottom: 10px">
<h3 style="text-align: center; margin: 0;">Skorašnje porudžbine</h3>
#{
int n = 5;
<table id="PorudzbineTable" style="width: 100%;margin-top: 10px; background-color: #ffbbbb; color: black">
#foreach (AR.TDShop.Porudzbina p in Model.User.Porudzbine)
{
<tr onclick="window.location.href='/Porudzbina?ID=' + #p.PorudzbinaID">
<td style="padding-left: 10px">#p.BrDokKom</td>
#switch (p.Status)
{
case AR.TDShop.Porudzbina.PorudzbinaStatus.NaObradi:
<td>Na obradi!</td>
break;
case AR.TDShop.Porudzbina.PorudzbinaStatus.CekaUplatu:
<td>Čeka uplatu!</td>
break;
case AR.TDShop.Porudzbina.PorudzbinaStatus.ZaPreuzimanje:
<td>Za preuzimanje!</td>
break;
case AR.TDShop.Porudzbina.PorudzbinaStatus.Preuzeto:
<td>Realizovano!</td>
break;
case AR.TDShop.Porudzbina.PorudzbinaStatus.Stornirana:
<td>Stornirano!</td>
break;
}
</tr>
n--;
if (n <= 0)
{
break;
}
}
</table>
<button id="SvePorudzbine" onclick="window.location.href='/User/Porudzbine'" style="text-align: center; margin-top: 10px; background-color: white; color: black">Sve porudzbine</button>
}
</div>
}
<div id="ObjasnjenjeCene">
<p>Cena bez PDV-a je iskazana crvenom bojom!</p>
</div>
}
<div style="padding: 15px; background-color: #5a5cd4; margin-bottom: 40px">
<button class="#if (#Model.ActivateGrupa == null && Model.ActivatePodgrupa == null) { #Html.Raw("activate") }" onclick="GoTo('/Proizvodi')">Svi proizvodi</button>
#foreach (GrupaModel g in Model.Grupe)
{
<button class="#if (Model.ActivateGrupa != null && Model.ActivateGrupa == g.GrupaID)
{
#Html.Raw("activate")
} else if (#Model.ActivatePodgrupa != null)
{
if(PodgrupaModel.GetParent((int)Model.ActivatePodgrupa) == g.GrupaID) { #Html.Raw("activate") }
}"
onclick="GoTo('/Proizvodi?GrupaID=#g.GrupaID')">
#g.Naziv
</button>
}
</div>
<div id="PredloziProizvod" style="border-top: black 2px; color: black;">
<button id="predloziButton" style="width: 100%; text-align: center">Predloži proizvod</button>
<input hidden type="text" placeholder="Naziv proizvoda" />
<input hidden type="text" placeholder="Kataloski broj" />
<input hidden type="text" placeholder="Opis primene" />
<button hidden id="PosaljiPredlogProizvoda">Posalji</button>
</div>
</div>
<div id="right" class="col-sm-9">
<div id="PretragaProizvoda">
<input type="text" placeholder="Pretraga..." value="#Model.Tag" />
<button id="tw" style="float: right" onclick="ToggleView(this)" value="0"><img src="~/images/View2.png" style="width: 25px" /></button>
</div>
<br />
#if (Model.PodGrupe.Count > 0)
{
string cls = "";
if (Model.ActivatePodgrupa == null)
{
cls = "aktivnaPodgrupa";
}
<div id="PodGrupe">
<button class="PodGrupa #cls" onclick="GoTo('/Proizvodi?GrupaID=#PodgrupaModel.GetParent((int)Model.PodGrupe[0].PodgrupaID))'">
<p>Svi proizvodi grupe</p>
</button>
#foreach (PodgrupaModel pgm in Model.PodGrupe)
{
cls = "";
if (pgm.PodgrupaID == Model.ActivatePodgrupa)
{
cls = "aktivnaPodgrupa";
}
<button class="PodGrupa #cls" onclick="GoTo('/Proizvodi?PodgrupaID=#pgm.PodgrupaID')">
<p>#pgm.Naziv</p>
</button>
}
</div>
<hr style="border-bottom: 2px solid black" />
}
#foreach (ProizvodModel p in Model.Proizvodi)
{
if (p.Aktivan)
{
string proizvodStil;
string buttonStil;
if (p.Klasifikacija == 0)
{
proizvodStil = "color: dimgray;";
buttonStil = "background: linear-gradient(to bottom, white, dimgray 20%, dimgray 80%, white 100%);";
}
else if (p.Klasifikacija == 2)
{
proizvodStil = "color: darkorange;";
buttonStil = "background: linear-gradient(to bottom, white, darkorange 20%, darkorange 80%, white 100%);";
}
else
{
proizvodStil = "color: darkgreen;";
buttonStil = "background: linear-gradient(to bottom, white, darkgreen 20%, darkgreen 80%, white 100%);";
}
<div class="proizvod ppppp #if (Model.Majstor) { #Html.Raw("korpa"); } normal"
#Html.Raw("onclick = \"GoToP('" + #p.ROBAID + "')\"") ;
style="#proizvodStil">
<p class="katBr">#p.KatBr</p>
<img src="#p.Slika" />
<p class="nazivProizvoda">#p.Naziv</p>
#if (Model.Majstor)
{
try
{
int NivoZaKorisnika = Model.User.Cenovnik_grupa.Where(x => x.Item1 == p.Cenovnik_GrupaID).Select(t => t.Item2).FirstOrDefault();
double VPCena = CeneZaKorisnika.Where(x => x.Item1 == p.ROBAID).FirstOrDefault().Item2;
double MPCena = VPCena + (VPCena * p.PDV / 100);
if (MPCena > 0)
{
<p class="vpcena">#VPCena.ToString("#,###.00") / #p.JM</p>
<p class="mpcena">#MPCena.ToString("#,###.00") / #p.JM</p>
if (Model.User.Vrsta == UserModel.Tip.Majstor)
{
<button style="#buttonStil" onclick="GoToP(#p.ROBAID); event.stopPropagation();"> KUPI!</button>
}
}
if (Model.User.Vrsta == UserModel.Tip.Administrator)
{
<button style="#buttonStil" onclick="Edit(#p.ROBAID); event.stopPropagation();">Detalji!</button>
}
}
catch (Exception ex)
{
#:alert("#ex.ToString()");
}
}
</div>
}
}
</div>
</div>
<div id="AlertPopUp">
</div>
<script src="~/js/AlertBox.js"></script>
<script>
var alb = new AlertBox($("#AlertPopUp"));
var currRID = -1;
var overwrite = false;
function GoTo(link) {
if ($("#tw").val() == 1) {
if (link.indexOf('?') > -1) {
window.location.href = link + "&V=1";
}
else {
window.location.href = link + "?V=1";
}
}
else {
window.location.href = link;
}
}
function GoToP(link) {
if ($("#tw").val() == 1) {
if (link.indexOf('?') > -1) {
window.location.href = link + "&V=1";
}
else {
window.location.href = link + "?V=1";
}
}
else {
window.location.href = "/Proizvod?ID=" + link;
}
}
function Edit(id) {
GoTo("/Proizvodi/Edit?ID=" + id);
}
function ToggleView(element) {
var curr = $(element).val();
if (curr == 1) {
$(element).val(0);
$(element).children("img").attr("src", "/images/View2.png");
$(".ppppp").removeClass("proizvod1");
$(".ppppp").addClass("block");
$(".ppppp").addClass("proizvod");
$(".korpa button").html("Dodaj u korpu!");
}
else {
$(element).val(1);
$(element).children("img").attr("src", "/images/View1.png");
$(".ppppp").removeClass("proizvod");
$(".ppppp").removeClass("block");
$(".ppppp").addClass("proizvod1");
$(".korpa button").html("<img src='/Images/cart.png' style='height: 50px;width: 50px;border-radius: 10px;padding: 5px;padding-right: 8px;background-color: #2196F3;' />");
}
}
#{
if(Model.View == 1)
{
#:StartOtherView();
}
}
function StartOtherView() {
$("#tw").val(1);
$("#tw").children("img").attr("src", "/images/View1.png");
$(".ppppp").removeClass("proizvod");
$(".ppppp").removeClass("block");
$(".ppppp").addClass("proizvod1");
$(".korpa button").html("<img src='/Images/cart.png' style='height: 50px;width: 50px;border-radius: 10px;padding: 5px;padding-right: 8px;background-color: #2196F3;' />");
}
$(function () {
var PredloziProizvodBlock = false;
$("#predloziButton").click(function () {
$(this).parent().children("input").each(function () {
if (PredloziProizvodBlock == true) {
$(this).hide();
}
else {
$(this).show();
}
});
if (PredloziProizvodBlock == true) {
$("#PosaljiPredlogProizvoda").hide();
}
else {
$("#PosaljiPredlogProizvoda").show();
}
PredloziProizvodBlock = !PredloziProizvodBlock;
})
$("#PosaljiPredlogProizvoda").click(function () {
$.ajax({
type: "GET",
url: "/Proizvodi/PosaljiPredlogProizvoda",
contentType: "application.json; charset-utf-8",
dataType: "json",
async: false,
success: function (data) {
alert(data);
},
error: function (data) {
alert(data);
}
});
})
$("#PretragaProizvoda input").keyup(function () {
var input = $(this).val().toUpperCase();
$(".proizvod").each(function () {
if ($(this).html().toUpperCase().indexOf(input) >= 0 || input.length == 0) {
$(this).show();
}
else {
$(this).hide();
}
});
});
});
</script>
All views use same layout.
Routing option:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
I think your problem with Redirect in you UserController, could your try replace it on RedirectToAction(); It's must be help you.
I found out mistake and it was so easy.
I thought i was checking all my code which is ran when entering some page but i forgot one big part and it is constructor:
private readonly IHostingEnvironment hostingEnvironment;
public ProizvodiController(IHostingEnvironment he)
{
hostingEnvironment = he;
Program.AbsolutePath = hostingEnvironment.WebRootPath;
Debug.FilePath = Path.Combine(Program.AbsolutePath, "Log");
}
public IActionResult Index(int? GrupaID, int? PodgrupaID, int? V, string Pretraga)
{
ProizvodiModel pm = new ProizvodiModel(GrupaID, PodgrupaID, V, Request);
pm.Tag = Pretraga;
return View(pm);
}
I forgot that constructor is accessed each time when you access any page from controller and it sets my AbsolutePath variable which i use later.
When i restart my server he lose all in memory data (which is static variable AbsolutePath) and it is only set when ANY user enter website but since i call it only in 2 controllers, other controllers were not working.
Solution was to add same code to all controllers constructors.

Fill a Form with controls (according to the data returned from service)

I am trying to migrate Model-driven-form to Reactive-form.
This is a dynamic form that gets filled according to data from getCommandPacket
this.renderSvc.getCommandPacket - is getting the data from the server, this is the function signature:
Server
..
[HttpGet("[action]")]
public Dictionary<string, string> GetCommandPacket(int ID){
..
}
..
Html
<form>
<div *ngFor="let key of commandKeys">
<span class="ui-float-label">
<textarea [id]="key" [name]="key" pInputTextArea [(ngModel)]="commandPacket[key]" style="width: 40em;"></textarea>
<label [for]="key">{{ key }}</label>
</span>
</div>
<p-button label="Add Field"></p-button>
<button p-button type="submit" icon="fa fa-angle-right" iconPos="right">
<span class="ui-button-text ui-clickable">Re-Submit</span>
</button>
</form>
TS
...
export class CommandPacketDetailsComponent implements OnInit {
#Input() id: number;
myForm: FormGroup;
constructor(private renderSvc: PfServerService, private fb: FormBuilder) {
}
commandPacket: { [key: string]: string; };
commandKeys: string[];
message: string = null;
ngOnInit() {
if (this.id !== 0 && typeof this.id !== "undefined")
this.getCommandPacket(this.id);
else
this.message = "No ID Given for Packet";
}
getCommandPacket(id: number) {
this.renderSvc.getCommandPacket(id).subscribe(data => {
this.commandPacket = data;
this.commandKeys = Object.keys(this.commandPacket);
});
}
...
how can I achieve the same result but in Reactive-form way?
You want to use FormArray. Declare form and within it, declare formArray. Then when you get your data from service, create as many formControls as you have results and add them to FormArray.
you have an example here:
https://angular.io/guide/reactive-forms#use-formarray-to-present-an-array-of-formgroups
form type:
yourForm:FormGroup;
form definition:
this.yourForm = this.fb.group({
yourFormArray: this.fb.array([])
});
make a getter for your formArray:
get yourFormArray(): FormArray {
return this.cpForm.get('commands') as FormArray;
}
and then once you get your data from server:
this.yourFormArray.reset();
this.commandKeys.forEach(val =>
this.yourFormArray.push(this.fb.group({ command: [''] }))
);
that will create as many command (without s) formGroups (having only one input field) as you have keys in your commandKeys result.
PS.
once you set that up you can use patchValue on formArray to fill it with actual values. something like:
this.myFormArray.patchValue(commandKeys.map(key => ({ command: key })));
PS2.
to clear form controls from formarray, you can use function like this:
//Clear formArray
clearItemsFormArray() {
while (this.yourFormArray.length > 0)
this.yourFormArray.removeAt(0);
}
yourFormArray is the one coming from getter.

Kendoui ComboBox prefetch & preselect item with server filtering

I need to see an example of a kendoui Combobox (either MVC or client side code) preselecting an item (not only value) from datasource.The datasource has server filtering enabled.The issue i am facing is that when i bind my mvc combobox to a model property (e.g. UserID), only the value (which is the user ID) is bound and not the Name which is the textfiled.When clicking on the combobox arrow, the selected item is not poping up,meaning that there is no selected item and only the widget element (e.g. input) value is set.Most of the examples i have seen shows how to set the selected value or text, but does not address the issue of the absence of a selected item.Here is my code:
#Html.Kendo().ComboBoxFor(model => model.UserID).DataValueField("ID").DataTextField("Name").Filter(FilterType.Contains).MinLength(3).DataSource(source =>
{
source.Custom().Type("aspnetmvc-ajax").Transport(transport => transport.Read(read =>
{
read.Action("GetAllUsers", "User");
})).ServerFiltering(true).ServerPaging(true).PageSize(50);
}).AutoBind(false)
The autoBind is false so that the combobox does not hit the data service with an empty filter which would return a useless 50 records.Instead of this, the desired behaviour is that the combobox datasource should send the filter (e.g: UserID=50) by default and should return the record and add the item to the combobox.I have found a workround for this issue but do not know if this the easiest way to do it:
combobox.dataSource.filter({ field: 'UserID', operator: 'eq', value: 50 });
If I call the above code, the item is preselected, and my combobox would have only one item which is what i wanted, but the next time i try to change the selected item by typing another user name, the filter would fail because the earlier filter is still attached to the datasource.I solved this by calling:
combobox.dataSource.filter().filters.shift()
Any help for finding a shortcut will be appreciated.
There's documentation for this here. The example below is taken from the page and based on DropDownList which is applicable to ComboBox too.
<div id="example">
<div class="demo-section k-header">
<h4>View Order Details</h4>
<p>
<label for="categories">Categories:</label><input id="categories" style="width: 270px" />
</p>
<p>
<label for="products">Products:</label><input id="products" disabled="disabled" style="width: 270px" />
</p>
<p>
<label for="orders">Orders:</label><input id="orders" disabled="disabled" style="width: 270px" />
</p>
<button class="k-button" id="get">View Order</button>
</div>
<style scoped>
.demo-section {
width: 400px;
}
.demo-section p {
margin-top: 1em;
}
.demo-section label {
display: inline-block;
width: 100px;
padding-right: 5px;
text-align: right;
}
.demo-section .k-button {
margin: 1em 0 0 105px;
}
.k-readonly
{
color: gray;
}
</style>
<script>
$(document).ready(function() {
var categories = $("#categories").kendoDropDownList({
optionLabel: "Select category...",
dataTextField: "CategoryName",
dataValueField: "CategoryID",
dataSource: {
type: "odata",
serverFiltering: true,
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Categories"
}
},
dataBound: function() {
this.search("Grains/Cereals");
this.select(this.selectedIndex);
}
}).data("kendoDropDownList");
var products = $("#products").kendoDropDownList({
autoBind: false,
cascadeFrom: "categories",
optionLabel: "Select product...",
dataTextField: "ProductName",
dataValueField: "ProductID",
dataSource: {
type: "odata",
serverFiltering: true,
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Products"
}
},
dataBound: function() {
this.search("Gnocchi di nonna Alice");
this.select(this.selectedIndex);
}
}).data("kendoDropDownList");
var orders = $("#orders").kendoDropDownList({
autoBind: false,
cascadeFrom: "products",
optionLabel: "Select order...",
dataTextField: "Order.ShipCity",
dataValueField: "OrderID",
dataSource: {
type: "odata",
serverFiltering: true,
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Order_Details?$expand=Order"
}
},
dataBound: function() {
this.search("Albuquerque");
}
}).data("kendoDropDownList");
});
</script>
</div>

Resources