Attaching an event to new element in Angular2 - javascript

I need to duplicate a new row on the click of + button. That new row contains a - button which will in turn delete that newly created row. So the problem is I could attach a click event to that new - button.
Below is the ts which contains the form :
import { Component, OnInit, ViewEncapsulation, ElementRef } from '#angular/core';
import { MailSegmentObject } from './mailSegmentObject';
import { MailSegmentRule } from './mailSegmentRule';
#Component({
selector : 'segment-form',
templateUrl : 'app/html/createSegment.html',
styleUrls : ['node_modules/bootstrap/dist/css/bootstrap.min.css'],
encapsulation : ViewEncapsulation.Native
})
export class CreateSegmentComponent {
counter : number = 0;
segment : MailSegmentObject = new MailSegmentObject();
addNewRule() : void {
var origElem = document.getElementById("mandatoryRule");
var copyElem = <HTMLDivElement>origElem.cloneNode(true);
copyElem.setAttribute("id", "mandatoryRule_" + (this.counter++));
copyElem.innerHTML += "<div class=\"col-sm-1\"><button type=\"button\" class=\"btn btn-default\" (click)=\"deleteRule(this)\">-</button></div>";
origElem.parentElement.appendChild(copyElem);
}
deleteRule(elem) : void {
console.log("asdasdasdasdasd");
elem.parentElement.removeChild(elem);
}
}
and html is:
<div class="container" style="margin-top: 15px;">
<form class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-2" for="Segment Name">Segment Name</label>
<div class="row">
<div class="col-sm-12">
<input type="text" class="form-control" id="segmentNameInput" placeholder="Segment Name">
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="pwd">Select Property</label>
<div class="row rule" id="mandatoryRule">
<div class="col-sm-3">
<select class="form-control">
</select>
</div>
<div class="col-sm-3">
<select class="form-control">
</select>
</div>
<div class="col-sm-3">
<input type="text" class="form-control">
</div>
</div>
<div class="col-sm-1">
<button type="button" class="btn btn-default" (click)="addNewRule(this)">+</button>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-8">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</div>
</form>
</div>
Kindly help me out.
Thanks.

This is written completely against the concept of angular2. You should use *ngFor on a collection of lines. Never ever -ever- use things like: getElementById, cloneNode, innerHTML, appendChild, removeChild.
My suggestion is that you take a closer look to the tutorials and cook book provided at angular.io, because I'm sorry, with the current state of your code, you are asking for a complete rewrite

Related

jQuery only run function for element that gets clicked

I got a small problem that i have no clue how to solve. This HTML/PHP code bellow gets different values from a database and outputs them into the different input fields.
The HTML/PHP bellow is one element, and multiple of them are made with different values from the database. Then i got a small javascript that calulates some different values from the values that are inputted. The problem is that i got lets say 5 elements, and only wants to calculate for one of them, but if i press the "btn-oppdater" button it calculates for all the different elements.
How do i make it only calculate for the element where the button is?
Script
$('.btn-oppdater').click(function(){
$(".kval_spill").each(function(){
var fieldShow = $(this).next('.kval_spill_inner');
var b_value_kval_1 = fieldShow.find('.b_value_kval_1')[0].value;
var b_odds_kval_1 = fieldShow.find('.b_odds_kval_1')[0].value;
var e_odds_kval_1 = fieldShow.find('.e_odds_kval_1')[0].value;
var gebyr_kval = '0.02'
var q_value = ((b_odds_kval_1 / (e_odds_kval_1 - gebyr_kval)) * b_value_kval_1);
var q_tap = (b_odds_kval_1 - 1) * b_value_kval_1 - (e_odds_kval_1 - 1) * q_value;
var q_value_fixed = q_value.toFixed(2);
var q_tap_fixed = q_tap.toFixed(2);
fieldShow.find('.q_value_1')[0].value = q_value_fixed;
fieldShow.find('.q_tap_1')[0].value = q_tap_fixed;
});
});
HTML/PHP
<?php while ($row = mysqli_fetch_assoc($result2)) { echo '
<form style="margin-top: 10px;" action="" method="post" class="">
<input type="hidden" class="kval_spill">
<div class="kval_spill_inner">
<input class="" type="hidden" name="id" value="'.$row['id'].'">
<div class="form-row">
<div class="form-group col-md-4">
<input type="text" class="form-control kval_kamp_1" name="kval_kamp_1" value ="'.$row['kval_kamp_1'].'" placeholder="Kamp">
</div>
<div class="form-group col-md-3">
<div class="input-group">
<input type="text"class="form-control b_value_kval_1" name="b_value_kval_1" value ="'.$row['b_value_kval_1'].'" placeholder="Spill verdi">
<div class="input-group-append">
<span class="input-group-text">Kr</span>
</div>
</div>
</div>
<div class="form-group col-md-2">
<input type="text" class="form-control b_odds_kval_1" name="b_odds_kval_1" value ="'.$row['b_odds_kval_1'].'" placeholder="Odds">
</div>
</div>
<div class="form-row">
<div class="form-group col-md-4">
<input type="text" class="form-control kval_marked_1" name="kval_marked_1" value ="'.$row['kval_marked_1'].'" placeholder="Type marked">
</div>
<div class="form-group col-md-3">
<div class="input-group">
<input type="text"class="form-control text-info q_value_1" name="q_value_1" value ="'.$row['q_value_1'].'" placeholder="Lay verdi">
<div class="input-group-append">
<span class="input-group-text">Kr</span>
</div>
</div>
</div>
<div class="form-group col-md-2">
<input type="text" class="form-control e_odds_kval_1" name="e_odds_kval_1" value ="'.$row['e_odds_kval_1'].'" placeholder="Odds">
</div>
</div>
<div class="form-row">
<div class="form-group col-md-2">
<div class="input-group">
<div class="input-group-append">
<span class="input-group-text">Tap</span>
</div>
<input type="text" class="form-control text-danger q_tap_1" name="q_tap_1" value ="'.$row['q_tap_1'].'" placeholder
="0.00" readonly>
<div class="input-group-append">
<span class="input-group-text">Kr</span>
</div>
</div>
</div>
<div class="col-auto">
<button type="button" class="btn btn-outline-secondary btn-oppdater">Regn ut</button>
</div>
</div>
</div>
</form>
<br>
'; }?>
Replace $(".kval_spill") with $(this).closest("form").find(".kval_spill").
But it looks like there's only one kval_spill and kvall_spill_inner in each form, so there's no need to use .each(). You can get rid of the .each() loop and just use:
var fieldShow = $(this).closest("form").find('.kval_spill_inner');
And instead of
fieldShow.find('.q_value_1')[0].value = q_value_fixed;
fieldShow.find('.q_tap_1')[0].value = q_tap_fixed;
you can write:
fieldShow.find('.q_value_1').val(q_value_fixed);
fieldShow.find('.q_tap_1').val(q_tap_fixed);

I'm trying to discard a bootstrap modal using Angular 6 when the server receives the data

Well, this is the component where I'm trying to create all the content. It is a crud that saves the data when and what I want is for the modal to disappear.
<div class="container">
<div class="table-wrapper">
<div class="table-title">
<div class="row">
<div class="col-sm-6">
<h2>Codigos De <b>Acceso.</b></h2>
</div>
<div class="col-sm-6">
<i class="material-icons"></i> <span>Agregar nuevo codigo</span>
</div>
</div>
</div>
<div class='col-sm-12 pull-right d-flex flex-row-reverse'>
<div id="custom-search-input">
<div class="input-group">
<input type="text" class="form-control" placeholder="Buscar" aria-label="Input group example" aria-describedby="btnGroupAddon2">
<div class="input-group-append">
<button class="btn btn-primary" id="btnGroupAddon2"><i class="fas fa-search"></i></button>
</div>
</div>
</div>
</div>
<div class='clearfix'></div>
<hr>
<div id="loader"></div>
<div id="resultados"></div>
<div class='outer_div'></div>
</div>
</div>
<!-- Add Modal HTML -->
<div id="addProductModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<form #dataForm="ngForm" (ngSubmit)="addData(dataForm)">
<div class="modal-header">
<h4 class="modal-title">Añadir Codigo</h4>
<button type="button" class="close" data-dismiss="modal" id="dismiss" aria-hidden="true">×</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Código</label>
<input type="text" name="code" class="form-control" #code="ngModel" [(ngModel)]="dataService.selectedData.code" required >
</div>
<div class="form-group">
<label>Dirección</label>
<input type="text" name="direction" class="form-control" #direction="ngModel" [(ngModel)]="dataService.selectedData.direction" required>
</div>
<div class="form-group">
<label>Comentario</label>
<input type="text" name="comment" class="form-control" #comment="ngModel" [(ngModel)]="dataService.selectedData.comment" required>
</div>
<div class="form-group">
<label>Tech #</label>
<input type="number" name="tech" class="form-control" #tech="ngModel" [(ngModel)]="dataService.selectedData.tech" required>
</div>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-secondary" data-dismiss="modal" value="Cancelar">
<input type="submit" class="btn btn-primary" value="Guardar datos">
</div>
</form>
</div>
</div>
</div>
<div class="center">
and this is my ts file:
import { Component, OnInit } from '#angular/core';
import { Data } from '../../models/data' // La ruta puede ser distinta.
import { DataService } from '../../services/data.service';
import { NgForm } from '#angular/forms';
#Component({
selector: 'app-datas',
templateUrl: './datas.component.html',
styleUrls: ['./datas.component.css'],
providers: [DataService]
})
export class DatasComponent implements OnInit {
constructor(private dataService: DataService) { }
ngOnInit() {}
addData(form: NgForm) {
this.dataService.postData(form.value)
.subscribe(res => {
this.resetForm(form);
})
}
/*
close(form?: NgForm){
if
}*/
resetForm(form?: NgForm) {
if(form){
form.reset();
var dismiss = document.querySelector('#addProductModal');
console.log(dismiss);
this.dataService.selectedData = new Data();
}
}
}
As you can see, that last method is called resetForm, I tried to clean the form when the data is sent and I have achieved it, but what I need is that the modal is discarded. Anyone have an idea?
NPM uninstall jQuery right away. Don't use the JavaScript version of bootstrap, install ngx-bootstrap and use the Angular components. They play much nicer with Angular. Your component should not be inspecting the DOM with querySelector and you shouldn't use any jQuery. If you rewrite the component using ngx-bootstrap you will be able to get an instance of an Angular modal component and call close.
https://valor-software.com/ngx-bootstrap/#/modals

Changing div inner HTML content by id in angular component method

I am trying to change inner HTML content of a div by id with another div in angular component method. I am able to call populateEndpointHomeContent() and get that content but not further content. Actually those methods populateAddEndpoint() and populateAddEndpointForm are not getting called on click. I am not getting any console error also. Any idea how I can get this?
endpoint.component.html
<div id="endpoint_home"></div>
<div id="endpoint_home_content" style="display:none">
<button class="btn btn-sm" (click)="populateAddEndpoint();">+ Add Endpoint</button>
</div>
<!-- Add Endpoint DIVS Starts -->
<div id="add_endpoint_home" style="display:none">
<form #endpointForm="ngForm">
<section class="form-block">
<div class="form-group">
<label for="endPointType">Select Endpoint Type</label>
<div class="select">
<select id="endPointType" (change)="populateAddEndpointForm(this.value);">
<option>MACHINE</option>
<option>K8S_CLUSTER</option>
<option>AWS</option>
<option>DOCKER</option>
<option>VCENTER</option>
<option>WAVEFRONT</option>
<option>VRNI</option>
</select>
</div>
</div>
<div id="add_endpoint_form"></div>
<button type="submit" class="btn btn-primary">ADD</button>
</section>
</form>
</div>
<div id="add_machine_form" style="display:none">
<div class="form-group">
<label for="name">Endpoint Name</label>
<input type="text" placeholder="Endpoint Name" size="42" id="name" name="name" [(ngModel)]="name" required>
</div>
<div class="form-group">
<label for="credentialsName">Credential Name</label>
<div class="select">
<select id="credentialsName">
<option>MACHINE</option>
</select>
</div>
</div>
<button type="button" class="btn btn-primary">ADD CREDENTIAL</button>
<div class="form-group">
<label for="host">Machine Host/IP</label>
<input type="text" placeholder="0.0.0.0" size="42" id="host" name="host" [(ngModel)]="host" required>
</div>
<div class="form-group">
<label for="sshPort">SSH Port</label>
<input type="number" placeholder="22" size="42" id="sshPort" name="sshPort" [(ngModel)]="sshPort" required>
</div>
<div class="form-group">
<label for="timeout">SSH Timeout</label>
<input type="number" placeholder="60" size="42" id="timeout" name="timeout" [(ngModel)]="timeout" required>
</div>
<div class="form-group">
<label for="osType">OS Type</label>
<div class="select">
<select id="osType">
<option>WINDOWS</option>
<option>LINUX</option>
</select>
</div>
</div>
</div>
<!-- Add Endpoint DIVS Ends -->
EndpointComponent
import { Component, OnInit } from '#angular/core';
import { EndpointService } from './endpoint.service';
#Component({
selector: 'app-endpoint',
templateUrl: './endpoint.component.html',
styleUrls: ['./endpoint.component.scss']
})
export class EndpointComponent implements OnInit {
constructor(private endpointService: EndpointService) { }
public wavefrontendpoints: any;
ngOnInit() {
this.populateEndpointHomeContent();
this.endpointService.getAllEndpoints().subscribe(res => this.wavefrontendpoints = res.response[0]);
}
public populateEndpointHomeContent() {
document.getElementById('endpoint_home').innerHTML = document.getElementById('endpoint_home_content').innerHTML;
}
public populateAddEndpoint() {
console.log('Inside populateAddEndpoint...');
document.getElementById('endpoint_home').innerHTML = document.getElementById('add_endpoint_home').innerHTML;
}
public populateAddEndpointForm(endPointType) {
console.log('Inside populateAddEndpointForm...');
if(endPointType === 'MACHINE') { document.getElementById('add_endpoint_form').innerHTML = document.getElementById('add_machine_form').innerHTML; }
}
}
Trying to render HTML content from its innerHTML will not have its prototype functions work.
Your HTML will be visible, but it won't make their click events trigger, because innerHTML only contains the HTML markup, not the function or event prototypes.
Go through Angular's Guide on Dynamic Component Loader, which is about loading dynamic content in an HTML page.

related UI not update in v-for

I have an array in my data object and it will push as many time user wants to add data to it, and it is rendering with v-for perfectly.
The problem is related UI part didn't update, see the following picture :
this is init of the page and there is an empty object in array
when I press add button panel-body would not update with new v-for generated elements:
thanks
EDIT:
When I write the code in pure pure html(copy it in code), it look like this, that is a target UI.
EDIT 2:
data :
data() {
return {
payment: {
type: "check",
checks: [{}]
}
}
}
ui :
<div v-for="(check,index) in payment.checks">
<br>
<h5>
index of array ->
{{index}}
</h5>
<div class="form-group">
<label class="col-md-3 control-label">
something
<label style="color:red">*</label>
</label>
<div class="col-md-9">
<input type="text" class="form-control" v-model="check.amount" />
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">
someting else
<label style="color:red">*</label>
</label>
<div class="col-md-9">
<input type="text" class="form-control" v-model="check.dadada" />
</div>
</div>
<div class="col-lg-8" style="padding-top: 3%;">
<button v-on:click="payment.checks.push({})" class="btn btn-success" style="margin-right: 7%;">
add
</button>
</div>
</div>

Dynamic ng-model with ng-repeat

I would like to create dynamically some input fields, that I used ng-repeat with ng-model. I meet some problems. ng-model without ng-repeat works correctly (transitPointStart). transits should work exactly the same, but they don't. What am I missing?
(link to plunker on the bottom)
transitPointStart:
<div class="col-lg-6">
<div class="form-group">
<label class="control-label" for="field_start">Start Point</label>
<input type="text" class="form-control" name="field_start" id="field_start"
ng-model="transitPointStart.city" placeholder="e.g. London"
/>
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
<label class="control-label" for="field_start_date">Date</label>
<div class="input-group">
<input id="field_start_date" type="text" class="form-control" placeholder="YYYY-MM-DD HH:MM"
name="field_start_date"
datetime-picker="{{dateformat}}" ng-model="transitPointStart.date"
is-open="datePickerOpenStatus.field_start_date"
/>
<span class="input-group-btn">
<button type="button" class="btn btn-default"
ng-click="openCalendar('field_start_date')"><i
class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
</div>
</div>
transits:
<div class="row" ng-repeat="transit in transits">
<!--TEST-->
<!--<div> Model: {{transit.modelName}} </div>-->
<!--<div> dateModel: {{transit.dateModelName}} </div>-->
<!--<div> datePicker: {{transit.datePickerName}} </div>-->
<!--<div> fieldName: {{transit.fieldName}} </div>-->
<!--<div> fieldDateName: {{transit.fieldDateName}} </div>-->
<!--<div> button: {{transit.buttonDateName}} </div>-->
<!--/TEST-->
<div class="col-lg-6">
<div class="form-group">
<label class="control-label" for="transit.fieldName">Transit {{$index+1}}</label>
<input type="text" class="form-control" name="transit.fieldName" id="transit.fieldName"
ng-model="transit.modelName" placeholder="transit"
/>
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
<label class="control-label" for="transit.fieldDateName">Date {{$index+1}}</label>
<div class="input-group">
<input id="transit.fieldDateName" type="text" class="form-control" placeholder="e.g"
name="transit.fieldDateName"
datetime-picker="{{dateformat}}" ng-model="transit.dateModelName"
is-open="transit.datePickerName"
/>
<span class="input-group-btn">
<button type="button" class="btn btn-default"
ng-click="transit.buttonDateName"><i
class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-2"></div>
<div class="col-lg-2">
<span class="btn btn-primary" ng-click="addTransit()" ng-if="transits.length < 3">Add transit</span>
</div>
<div class="col-lg-2"></div>
</div>
controller:
$scope.transits = [];
$scope.addTransit = function () {
var tempId = $scope.transits.length + 1;
var tempName = "transitPoint_" + tempId;
var tempModelName = tempName + ".city"; // Here I would like to have access to transitPoint.city
var tempDateName = tempName + ".date"; // as above (transitPoint.date)
var tempDate = "datePickerOpenStatus.field_transit_date_" + tempId;
var tempFieldName = "field_transit_" + tempId;
var tempFieldDateName = "field_transit_date_" + tempId;
var tempButton = "openCalendar('" + tempFieldDateName + "')";
$scope.transits.push({
modelName: tempModelName,
dateModelName: tempDateName,
datePickerName: tempDate,
fieldName: tempFieldName,
fieldDateName: tempFieldDateName,
buttonDateName: tempButton
});
}
/*
{...} - rest of code, sending queries (vm.save() ect.)
*/
$scope.datePickerOpenStatus = {};
$scope.datePickerOpenStatus.field_start_date = false;
$scope.datePickerOpenStatus.field_end_date = false;
// I should've used loop here
$scope.datePickerOpenStatus.field_transit_date_1 = false;
$scope.datePickerOpenStatus.field_transit_date_2 = false;
$scope.datePickerOpenStatus.field_transit_date_3 = false;
$scope.openCalendar = function (date) {
$scope.datePickerOpenStatus[date] = true;
};
Demo: Plunker
Some of the bindings in your HTML are not correct. You need to use interpolation (the {{ }} format) whenever you need to emit data from the model into the HTML.
For example, when assigning IDs, you have:
<input id="transit.fieldDateName" type="text" class="form-control" placeholder="e.g" name="transit.fieldDateName" ...
This should be:
<input id="{{transit.fieldDateName}}" type="text" class="form-control" placeholder="e.g" name="{{transit.fieldDateName}}" ...
Second, your ng-click syntax is not correct. You should not create the openCalendar expression in JavaScript, but in your HTML, like so:
<button type="button" class="btn btn-default" ng-click="openCalendar(transit.fieldDateName)">
I think your Plnkr is missing some scripts and/or steps to make the calendar work, but these changes will at least cause your openCalendar function to get called.

Categories