Copy ID from nested element to its top parent using jQuery - html

I have the following situation in my HTML created by a plugin:
<div class="form-controls">
<div class="form__field ">
<div class="preferences__notification">
<label id="user_comment" class="form-label"></label>
</div>
</div>
</div>
<div class="form-controls">
<div class="form__field ">
<div class="preferences__notification">
<label id="wall_post" class="form-label"></label>
</div>
</div>
</div>
The above HTML is around 20 repeating elements long and I am trying to call the individual main parents form-controls so I can add unique CSS or jQuery. The only unique identity in this HTML is on the nested label. So there are 20x unique <label> IDs. So I was wondering how I could get the label id copied to its top parent `form-controls' with jQuery, so the outcome would be for the first one:
<div id="user_comment" class="form-controls">etc</div>
Update Solution
My initial request to add the same id from the <label> into the top parent is HTML wise not clever to do. So the accepted answer is okay, but not ideal. To make it more HTML valid, I have chosen to take the <label id= name as an additional class for the top parent. So ultimate solution will be this:
jQuery(".form-controls").each(function() {
var label_id_name = jQuery(this).find('label').attr('id');
jQuery(this).addClass(label_id_name);
});
And HTML outcome:
<div class="form-controls user_comment">
<div class="form__field ">
<div class="preferences__notification">
<label id="user_comment" class="form-label"></label>
</div>
</div>
</div>
<div class="form-controls wall_post">
<div class="form__field ">
<div class="preferences__notification">
<label id="wall_post" class="form-label"></label>
</div>
</div>
</div>

ANSWER UPDATE: - Copy label ID to div class
This is the preferred way to accomplish this to avoid conflicting ID'S
jQuery(".form-controls").each(function() {
var label_id_name = jQuery(this).find('label').attr('id');
jQuery(this).addClass(label_id_name);
});
OLD ANSWER - copying ID from label to div.
You can copy the id attribute of each nested label by looping through all div with form-control class.
$(".form-controls").each(function()
{
var label_id = $(this).find('label').attr("id");
$(this).attr("id", label_id);
});
In your code the outcome will be:
<div class="form-controls" id="user_comment">
<div class="form__field ">
<div class="preferences__notification">
<label id="user_comment" class="form-label"></label>
</div>
</div>
</div>
<div class="form-controls" id="wall_post">
<div class="form__field ">
<div class="preferences__notification">
<label id="wall_post" class="form-label"></label>
</div>
</div>
</div>
This will loop each div with the class of .form-controls and change it's ID to it's label descendant ID.
Keep in mind this is not the best practice since id's are meant to be unique. Consider using class instead.
You can also add the following code at the end of the loop to remove the label's ID after copying them.
$(this).find('label').removeAttr("id");

Here you go! I have pasted code below, please have a look.
const addIDToParent = ele => {
for (var i = 0; i < ele.length; i++) {
let getId = $(ele[i]).find('label').attr('id');
$(ele[i]).attr('id', getId);
}
};
addIDToParent($('.form-controls'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div class="form-controls">
<div class="form__field ">
<div class="preferences__notification">
<label id="user_comment" class="form-label">User Comment</label>
</div>
</div>
</div>
<div class="form-controls">
<div class="form__field ">
<div class="preferences__notification">
<label id="wall_post" class="form-label">Wall Post</label>
</div>
</div>
</div>
</body>
</html>

Related

Add CSS Class to Row Elements If Value Equals

Using JQuery I would like to check the value of an input, if it equals Complete I would like to add the Bootstrap class is-valid to that input, and all the other inputs on the same row.
Something like this (pseudo code);
if wb_status_reg = Complete {
// add is-valid to all row inputs / select boxes
}
I should note that sometimes the row will contain a select box, not just text inputs. Also, I'm unable to edit the html as it's being generated by a form builder component (in a CMS).
My code is currently working but I know it's too long and could be improved. In my code i'm showing one form-row but I actually have many more, so I need to duplicate this a few more times.
How can I achieve this in a more efficient way?
jQuery(document).ready(function($) {
var wb_stage_reg = $('#wb_stage_reg');
var wb_status_reg = $('#wb_status_reg');
var wb_date_reg = $('#wb_date_reg');
setIsValid($);
});
function setIsValid($) {
wb_stage_reg = ($(wb_status_reg).val().trim() == "Complete") ? $(wb_stage_reg).addClass("is-valid") : "";
wb_status_reg = ($(wb_status_reg).val().trim() == "Complete") ? $(wb_status_reg).addClass("is-valid") : "";
wb_date_reg = ($(wb_status_reg).val().trim() == "Complete") ? $(wb_date_reg).addClass("is-valid") : "";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-row">
<div class="col-3">
<div class="form-group rsform-block-wb-stage-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control" id="wb_stage_reg" name="form[wb_stage_reg]" type="text" value="Registration"><span></span>
</div>
</div>
</div>
</div>
<div class="col-3">
<div class="form-group rsform-block-wb-status-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control" id="wb_status_reg" name="form[wb_status_reg]" type="text" value="Complete"><span></span>
</div>
</div>
</div>
</div>
<div class="col-3">
<div class="form-group rsform-block-wb-date-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control" id="wb_date_reg" name="form[wb_date_reg]" type="text" value="2020-06-08 09:41:40"><span></span>
</div>
</div>
</div>
</div>
</div>
Something like this:
You need to change ID to class on all fields
Since you cannot, I use the name instead:
$(function() {
$("[name='form[wb_status_reg]']").each(function() {
const $parent = $(this).closest(".form-row");
const complete = this.value === "Complete";
$parent.find("[name='form[wb_date_reg]'], [name='form[wb_stage_reg]']").toggleClass("is-valid",complete)
})
});
.is-valid { color:green}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-row">
<div class="col-3">
<div class="form-group rsform-block-wb-stage-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control wb_stage_reg" name="form[wb_stage_reg]" type="text" value="Registration"><span></span>
</div>
</div>
</div>
</div>
<div class="col-3">
<div class="form-group rsform-block-wb-status-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control wb_status_reg" name="form[wb_status_reg]" type="text" value="Complete"><span></span>
</div>
</div>
</div>
</div>
<div class="col-3">
<div class="form-group rsform-block-wb-date-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control wb_date_reg" name="form[wb_date_reg]" type="text" value="2020-06-08 09:41:40"><span></span>
</div>
</div>
</div>
</div>
</div>

select a particular tuple in angular

in my angular application i have a list of schedule objects in schedule array that are displayed using ngFor.
i want that whenever i click the checkbox on the left of my schedule box that particular schedule is selected as current schedule and rest is set to false .
i also want that my default selected schedule is the one that is most recently added to the array.
here is my HTML code
<div class="Box" *ngFor="let schedule of availableSchedules">
<div class="row width100">
<div class="col-md-1">
<div class="container">
<div class="round">
<input type="checkbox" id="checkbox" />
<label for="checkbox"></label>
</div>
</div>
</div>
<div class="col-md-11">
<div class="row width100" style="font-size: larger;">
<div class="col-md-4">
From : <span>{{schedule.startTime}}</span>
</div>
<div class="col-md-4">
To : <span>{{schedule.endTime}}</span>
</div>
<div class="col-md-2"></div>
</div>
<label for="days" style="font-size: larger;">Days</label>
<div class="row" name="days" style="margin-top: 5px;padding-left: 5px;">
<span class="chip" *ngFor="let day of schedule.days">{{day}}</span>
</div>
</div>
</div>
</div>
here is my ts code
currentSchedule = new tutorAvailablitySchedule();
availableSchedules: tutorAvailablitySchedule[] = [];
selectSchedule(schedule:tutorAvailablitySchedule) {
this.currentSchedule = schedule;
console.log(event);
}
That you should do the job:
<input type="checkbox"
[ngModel]="schedule===currentSchedule"
(ngModelChange)="selectSchedule($event ? schedule : null)" />
If you need to prevent an empty selection, you should use a radio button instead. In that case, you don't event need to define the selectSchedule function:
<input type="radio" name="schedule"
[value]="schedule"
[(ngModel)]="currentSchedule"/>

Angular 6 - click to make a div editable

Using Angular 6, I have the html below and would like to click the edit text to make the div containing Detail$.Title editable.
Im trying to do it as per this SO post
<div class="col-sm-6">
<div class="card text-left" >
<div class="card-header text-secondary">Title <small class="pull-right text-danger" (click)="setTitleEdit()">Edit Text</small></div>
<div class="card-body">
<span *ngIf="!cd.canEditCode">{{Detail$.Title}}></span>
<input *ngIf="cd.canEditCode" type="text" class="form-control" />
<p class="card-text text-secondary">{{ Detail$.Title}}</p>
</div>
</div>
intellisense doesn't like the forEach or canEditCode below, I know Im missing something, just not sure what, Im unsure where the canEditCode is coming from in the linked post. In my ts file Detail$ is an object containing the data returned from a call
getEventDetail(): void {
this.data.getDetail(this.id)
.subscribe(data => this.Detail$ = data);
}
setTitleEdit(){
this.Detail$.forEach(t => t.canEditCode = false)
this.Detail$.canEditCode=true
}
try like this
<div class="col-sm-6" *ngFor="let item of detailItems">
<div class="card text-left">
<div class="card-header text-secondary">{{item.title}}
<small class="pull-right text-success" (click)="item.canEditCode = true">Edit</small>
<small class="pull-right text-danger" (click)="item.canEditCode = false">Close</small>
</div>
<div class="card-body">
<span>{{item.name}}</span>
<input *ngIf="item.canEditCode" [(ngModel)]="item.name" type="text" class="form-control" />
</div>
</div>
[(ngModel)]="item.name" make two way binding to item property (name)
stackblitz demo
I think it's easier to use native HTML input for editing and viewing with ngModel and style options.
Simply like this:
<input type="text" [(ngModel)]="title" class="editable">
And for CSS class:
.editable{
border:none;
outline:none;
background:transparent;
}
That's should work.

How to generate DIV dynamically from Sql data from server in AngularJS file?

I have to add element as per the data coming from mssql server in the following area :
<div id="ApplicationForm" class="tabcontent" style="display:none;">
<div class="tab_section">
<div class="container">
<div class="row">
<div class="col-lg-12" style="font-size:16px;">Application Form</div>
<div class="col-lg-12">
<div class="" style="width:100%;border-bottom:1px solid #ddd;padding-top:5px;margin-bottom:10px;"></div>
</div>
</div>
<div ng-bind-html="applnformdata"> //from here on the data should be dynamic
</div>
</div>
</div>
</div>
</div>
</div>
(Sorry if I left any ending div tag).
On click of a button I'm calling a function in angularJs
$scope.dynamicdata=function(){
Method.getbyId("xxxxxxxxxxxx", Id).then(function (response) {
var newEle = '';
for ( i = 0; i < response.data.length;i++){
newEle += "<div class='form-group col-lg-6'>< label class='form_lable' >" + response.data[i].fieldName + "</label ><div class='m_settings_cell'><input type='checkbox' class='m_switch_check' value='1' entity='Test 1'></div></div>"; //when I try to do this it doesnot loads the <label> tag at all
}
$scope.applnformdata = newEle;
}).catch(function (data) {
console.log("access not allowed");
});
}
and I have some entries coming from mssql which have "label name" and checkbox values . How can I make this part to generate dynamically ? Like if 10 entried come then 10 data will be shown , if 5 then 5 and so on ? Please help.
Rather than appending the "div" and using default jquery checkbox, made own switch and used it.
<div class="row">
<div class="form-group col-lg-6" ng-repeat="x in apform">
<div class="col-lg-6">
<label class="form_lable">{{x.fieldName}}</label>
</div>
<div class="col-lg-6" align="right">
<label class="switch">
<input id="{{x.id}}" class="switch-input" type="checkbox" ng-model="x.fieldOption" ng-click="check(x.id)" />
<span id="data_{{x.id}}" class="switch-label" data-on="" data-off=""></span>
<span class="switch-handle"></span>
</label>
</div>
</div>
</div>

How to get data from a div in AngularJS

I use an input text to put text in div. When I write something in the input and I press the key Enter, the text from the input field is added to a div just below and normally, an array should be updated in my controller with the new value. I don't know how can I get the list of element text added to the div from a controller.
I'm trying to use the property n-change on my div with ng-model but it doesn't work.
<div class="row center" id="searchD" >
<form id="search" >
<input type="text" id="searchInput" onchange="createTag($(this).val());"/>
</form>
</div>
<div class="row center" ng-controller="Mainctrl">
<div id="tagContainer" ng-model="tagList" ng-change="tagList()">
</div>
</div>
You could do it something like below if that is what you are expecting.
Html :
<div class="row center" id="searchD" ng-controller="Mainctrl">
<form id="search" >
<input type="text" id="searchInput" ng-model="tagInput" ng-change="addTag()"/>
</form>
</div>
<div class="row center">
<div id="tagContainer" ng-repeat="tag in tagList">{{tag}}
</div>
</div>
Mainctrl:
$scope.tagList = [];
$scope.addTag = function () {
$scope.tagList.push($scope.tagInput);
$scope.tagInput = '';
}
Are you asking how to get data from the controller onto the html page? If so, you just use angular interpolation {{ someData }}
<div id="tagContainer" ng-model="tagList" ng-change="tagList()">
{{ tagList }}
</div>