Printing multiple ng-repeat elements in a single row - angularjs-ng-repeat

I have a list of item and ng-repeat display them in the page. Below is the simplified structure -
[
{
"id": "elem-1",
"position": {
"row": 1,
"column": 1
}
},
{
"id": "elem-2",
"position": {
"row": 2,
"column": 1
}
},
{
"id": "elem-3",
"position": {
"row": 2,
"column": 2
}
}
]
Now elem-1 should come in first row, while the second row should have elem-2 and elem-3, side-by-side. I have checked ng-repeat-start and also gone through the existing similar topics in Stack overflow but not sure how to do this. This is my HTML template
<div layout="row" ng-repeat="item in inputElemAll">
<div ng-if="if the current row has 1 column">
<md-input-container class="md-block">
<!-- Print the element-->
</md-input-container>
</div>
<div ng-if="if current row has more than 1 column">
<md-input-container class="md-block" flex="33">
<!-- Print the element-->
</md-input-container>
</div>
</div>
All I'm trying here is to add a flex attribute in case I have to show more columns in a single row. But the problem is, with every ng-repeat a new <div> with "row" layout is started and I'm stuck here. Not sure how to access multiple ng-repeat elements and also be on the same <div> simultaneously.
P.S. I use material layout, in case you are interested.

I am assuming that you wanna show your array like a table and maximum rows/columns are not greater than length of your array. You have to use two loops with ng-repeat, first one is for all rows and seconds one is for columns. also use 'orderBy' to sort. I mixed your json array and the result is as expected:
<div layout="row" ng-repeat="row in inputElemAll">
<div ng-repeat="item in inputElemAll | orderBy:'position.column'">
<div ng-if="$parent.$index==item.position.row-1">
<md-input-container class="md-block">
{{item.id}}
</md-input-container>
</div>
</div>
</div>
Check this jsFiddle working example:
http://jsfiddle.net/hd1by95r/47/

Related

CKEditor4 mentions output template not outputting entire templated string in wysiwyg editor and being inserted as new <p> tag instead of inline

I'm having a few issues implementing the Mentions plugin in CKEditor4:
The outputTemplate isn't acting as expected. The <span class="tag is-delete"></span> from the template is completely omitted when inserted into the editor after selecting from the mentions dropdown.
The outputTemplate is inserted in a separate <p> tag all by itself, whereas I want the tags to be inline.
Example of current output:
<p>After looking into this issue, I can confirm</p>
<p><a data-value="1" class="tags has-addons"><span class="tag is-info">John Doe</span></a></p>
<p>'s bug report is reproducible in all major production releases; therefore, further escalation is required.</p>
Example of expected/desired output:
<p>After looking into this issue, I can confirm <a data-value="1" class="tags has-addons"><span class="tag is-info">John Doe</span><span class="tag is-delete"></span></a>'s bug report is reproducible in all major production releases; therefore, further escalation is required.</p>
My relevant code
My exact CKEditor configuration can be viewed here.
I'm using the Div Editing Area plugin in place of the iframe, so that my global css (Bulma) is utilized for the tags inside the wysiwyg editor.
<div class="field">
<p class="control" id="discussion-inputs">
<textarea id="discussion-textarea" class="textarea" placeholder="Add a comment..." style="margin-top: 0px; margin-bottom: 0px; height: 128px;"></textarea>
</p>
</div>
CKEDITOR.replace( document.querySelector( '#discussion-textarea' ), {
allowedContent: true,
mentions: [
{
marker: '#',
minChars: 3,
feed: "{{ url_for('api.user_list') }}",
itemTemplate: '<li data-id="{id}" class="dropdown-item">{name}</li>',
outputTemplate: '<a data-value="{id}" class="tags has-addons"><span class="tag is-info">{name}</span><span class="tag is-delete"></span></a>'
}
]
});
Small sample of the output received from the api.user_list endpoint
[
{
"email": "johnd#email.com",
"id": 1,
"name": "John Doe"
},
{
"email": "janed#email.com",
"id": 2,
"name": "Jane Doe"
}
]
My questions
How can I make the entire outputTemplate actually output without being truncated or stripped of any of the supplied html tags/classes?
How can I make sure the tags are inserted inline instead of as separate, new <p> tags, so there are no unneccessary linebreaks added to the typed message?
Bonus: How can I make it so the mention tag, after it's properly inserted into the editor area, when clicked will be removed instead of the cursor being placed at the spot of the text that was clicked? The idea is to prevent the user from being able to modify the #'d username to one that is not valid.

vuetify list perfomance issue

I have a simple json array which consist of object like this
{
"kb:esid": "779256bf333d2d11abb52e39aafff20d",
"kb:station": "Disco935 New York's Jammer",
"kb:description": "Playing The 70's 80's 90's Disco And Beyond",
"kb:station_url_record": {
"kb:url_no": "1",
"kb:url": "http://localhost/stream",
"kb:status_code": "A",
"kb:bandwidth_kbps": "128",
"kb:url_strength": "9"
}
}
I use vuetify on codrova project to render list. The list consist of 3 lines: station, description and bandwidth. There is also a simple component to mark a station as a favourite.
The list rendering takes about 5 seconds to render ~200 elements. I'm using a bit old smartphone: 2GB memory, 5.1 Android, ~1.2 GHz CPU.
How can I increase the render speed? I tried to search infinity list in vuetify but there is nothing about it.
Thanks.
Vue.js is a little bit heavy to load however you can use lazy initialization by implementing an infinite scroll component. There is an implemented component called vue-mugen-scroll. It also has a CDN link if you need a quick test.
Just replace getStations method with your asynchronous server call and it is done. Check this snippet to see how it works.
let vm = new Vue({
el: '#vue-instance',
data: {
stations: [],
loading: false,
},
created() {
this.getStations();
},
methods: {
getStations() {
for (let i = 0; i < 16; i++) {
const count = this.stations.length + i;
this.stations.push({
esid: '779256bf333d2d11abb52e39aafff20d' + count,
name: 'Station ' + count,
description: 'Station Description ' + count,
record: 'Station Record ' + count,
});
}
},
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vue-mugen-scroll#0.2.5/dist/vue-mugen-scroll.min.js"></script>
<div id="vue-instance" class="container">
<div class="row">
<div class="col-sm-6" v-for="(station, index) in stations">
<div class="card m-4" style="width: 18rem;">
<div class="card-body">
<h3 class="card-title">{{ station.name }}</h3>
<p>{{ station.esid }}</p>
<p>{{ station.description }}</p>
<p>{{ station.record }}</p>
</div>
</div>
</div>
</div>
<mugen-scroll :handler="getStations" :should-handle="!loading">
loading...
</mugen-scroll>
</div>

Laravel data best practices

I'm new at Laravel and I want to know what best practices are for that :
I have a bunch of item I got with my query. It returns me something like that :
[{"id_equipement":24,"id_typeequipement":5, "imgequipement":xxxx},
{"id_equipement":30,"id_typeequipement":8, "imgequipement":xxxx}]
I have now 15 div to fill (see image below). One div represents one type and I want to know how to check if my first record goes to my second div background image, my second record goes to my third div...
I don't really know how to split in order to check...
Here is my html code:
<div class="item-frame-vertical" id="item-hat">
<div class="item-inner-frame"
style="background-image: url({{ asset('images/item_display/headgear.png') }})"></div>
</div>
<div class="item-frame-vertical" id="item-necklace" data-target="lol">
<div class="item-inner-frame"
style="background-image: url({{ asset('images/item_display/amulet.png') }})"></div>
</div>
<div class="item-frame-vertical" id="item-chest">
<div class="item-inner-frame"
style="background-image: url({{ asset('images/item_display/breastplate.png') }})"></div>
</div>
How can I check :
If the first record is type "5", it belongs to my 8th div
I was intending to do 15 query and give my controller 15 array and check for each div if there is a single record but I'm not sure this is the best way to do it because I must make 15 queries...
The way I'm doing it, I feel that I have to go through my result 15 times with a foreach and then check the type like :
#foreach ($entries as $entry)
if($entry->type_equipement == 5)
{
$img = $entry->img_equipement;
}
else
{
$img = images/item_display/breastplate.png
}
#endforeach
<div class="item-inner-frame" style="background-image:
url({{ asset('$img') }})"></div>
</div>
EDIT :
To be more precise... If I have the :
record with 'id_typeequipement' 5 I must change the background of the div 'item-hat' by 'img_equipement' from my record
record with 'id_typeequipement' 7 I must change the background of the div 'item-chest' by 'img_equipement' from my record
and this, for 15 div

Getting child elements using cssSelector

I have a code segment that looks like this
<div class="class1">
<div class="ng-scope"> apple </div>
<div class="ng-scope"> butter </div>
I want to get the text of the children. I do not want to use ng-scope since that is not a unique identifiter, but class1 is. How can I do something like identifying the parent, so ('.class1') or using xpath, and then getting the text from all its children. so the print out would look something like
" [ apple, butter ]; "
$$('.class1 div').getText().then(function(values) {
// This is an array containing ['apple', 'butter']
});

How can I validate a group within another group and maintain separate error messages?

I'm trying to use the 'require_from_group_update' method with jquery validator and have run into a snag I need help with. I working with multiple forms (24 in total) and each has many, many fields. In some instances, I need to validate groups of questions. As long as the groups are exclusive, this works great, but in some instances, for example, I need to have 5 total answers but at least 3 from the last 4 questions.
So that could mean 1 question in the first group is required and 4 from the second or 2 from the first and 3 from the second, etc. In my real form, the forms have between 10 and 20 questions long with different required counts for each.
I created the example with the fields in separate groups but really wanted to see if it was possible to check if 3 of the last 4 questions are answered and that 5 out of the total 8 are also answered. I tried to have all questions in one group and the last 4 in another - but that didn't work. Here I just picked 8 as example - in reality, there can be 10 to 20 total questions with varying requirements for each.
Many thanks in advance - I hope this is clear and concise enough.
Sample code is below - or there's a fiddle as well - jsfiddle.net/43rdworld/qZ6rn/4/
<!DOCTYPE html>
<html lang="en">
<head>
<title>Online Nomination Form</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script>
<script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.11.0/jquery.validate.js"></script>
<style type="text/css" media="all">
textarea {margin-left:20px;}
.wrapper {width: 200px;clear:both;float:left;margin-bottom:10px;}
div.errorContainer {width:200px;float:left;font-size:9pt;}
</style>
<script>
$(document).ready(function () {
$("#theForm").validate({
groups: {
group1: "sm_Appreciation,sm_Impact,sm_Safety,sm_People,sm_Parents,sm_Goals,sm_Money,sm_Decision",
group2: "sm_Parents,sm_Goals,sm_Money,sm_Decision"
},
rules: {
sm_Appreciation: {require_from_group_updated: [2, ".smg1"]},
sm_Impact: {require_from_group_updated: [2, ".smg1"]},
sm_Safety: {require_from_group_updated: [2, ".smg1"]},
sm_People: {require_from_group_updated: [2, ".smg1"]},
sm_Parents: {require_from_group_updated: [3, ".smg2"]},
sm_Goals: {require_from_group_updated: [3, ".smg2"]},
sm_Money: {require_from_group_updated: [3, ".smg2"]},
sm_Decision: {require_from_group_updated: [3, ".smg2"]},
},
errorPlacement: function(error, element) {
if ((element.attr("name") === "sm_Appreciation") || (element.attr("name") === "sm_Impact") || (element.attr("name") === "sm_Safety") || (element.attr("name") === "sm_People")) {
error.appendTo("#smError1");
} else if ((element.attr("name") === "sm_Parents") || (element.attr("name") === "sm_Goals") || (element.attr("name") === "sm_Money") || (element.attr("name") === "sm_Decision")) {
error.appendTo("#smError2");
}
},
});
jQuery.validator.addMethod('require_from_group_updated', function (value, element, options) {
var numberRequired = options[0];
var selector = options[1];
var fields = $(selector, element.form);
var filled_fields = fields.filter(function () {
// it's more clear to compare with empty string
return $(this).val() != "";
});
var empty_fields = fields.not(filled_fields);
// we will mark only first empty field as invalid
if (filled_fields.length < numberRequired && empty_fields[0] == element) {
return false;
}
return true;
// {0} below is the 0th item in the options field
}, jQuery.format("* Please fill out at least {0} of these fields."));
});
</script>
</head>
<body>
<form name="theForm" id="theForm" method="post" action="" autocomplete="off">
<h4>Answer 5 of the following 8 questions, with at least 3 from questions 4-8</h4>
<div class="wrapper">
<label for="sm_Appreciation">1. Question 1</label><br>
<textarea name="sm_Appreciation" id="sm_Appreciation" class="smg1" rows="3" cols="20" maxlength="200" tabindex="1"></textarea>
</div>
<div id="smError1" class="errorContainer"></div>
<div class="wrapper">
<label for="sm_Impact">2. Question 2</label><br>
<textarea name="sm_Impact" id="sm_Impact" class="smg1" rows="3" cols="20" maxlength="200" tabindex="2"></textarea>
</div>
<div class="wrapper">
<label for="sm_Safety">3. Question 3</label><br>
<textarea name="sm_Safety" id="sm_Safety" class="smg1" rows="3" cols="20" maxlength="200" tabindex="3"></textarea>
</div>
<div class="wrapper">
<label for="sm_People">4. Question 4</label><br>
<textarea name="sm_People" id="sm_People" class="smg1" rows="3" cols="20" maxlength="200" tabindex="4"></textarea>
</div>
<h4 style="clear:both;">Answer at least 3 questions from questions 4 through 8</h4>
<div class="wrapper">
<label for="sm_Parents">5. Question 5</label><br>
<textarea name="sm_Parents" id="sm_Parents" class="smg2" rows="3" cols="20" maxlength="200" tabindex="5"></textarea>
</div>
<div id="smError2" class="errorContainer"></div>
<div class="wrapper">
<label for="sm_Goals">6. Question 6</label><br>
<textarea name="sm_Goals" id="sm_Goals" class="smg2" rows="3" cols="20" maxlength="200" tabindex="6"></textarea>
</div>
<div class="wrapper">
<label for="sm_Money">7. Question 7</label><br>
<textarea name="sm_Money" id="sm_Money" class="smg2" rows="3" cols="20" maxlength="200" tabindex="7"></textarea>
</div>
<div class="wrapper">
<label for="sm_Decision">8. Question 8</label><br>
<textarea name="sm_Decision" id="sm_Decision" class="smg2" rows="3" cols="20" maxlength="200" tabindex="8"></textarea>
</div>
<div style="clear:both;"><input type="submit" value="submit"></div>
</form>
</body>
</html>
First I updated the plugin to version 1.11.1 and I included the corresponding version of the additional-methods.js file. Version 1.11.1 is where all the bugs were finally fixed in the require_from_group method.
Then I simply created a group within a group. You already have the right idea with your groups option, but that's only used for consolidating the error messages. Since your whole form is one group, you have to apply the require_from_group rule to all fields. Then since you have another unique group within it, you have to again apply the require_from_group rule to only those fields.
rules: {
sm_Appreciation: {
require_from_group: [5, ".smg1"]
},
sm_Impact: {
require_from_group: [5, ".smg1"]
},
sm_Safety: {
require_from_group: [5, ".smg1"]
},
sm_People: {
require_from_group: [5, ".smg1"]
},
sm_Parents: {
require_from_group: [5, ".smg1"],
require_from_group: [3, ".smg2"]
},
sm_Goals: {
require_from_group: [5, ".smg1"],
require_from_group: [3, ".smg2"]
},
sm_Money: {
require_from_group: [5, ".smg1"],
require_from_group: [3, ".smg2"]
},
sm_Decision: {
require_from_group: [5, ".smg1"],
require_from_group: [3, ".smg2"]
}
},
And finally, you can clean up your errorPlacement by using the class name rather than manually checking against each field name. I also removed the .appendTo() method because it just keeps repeating the error message creating a whole string of the same message over and over.
errorPlacement: function (error, element) {
// if it's only part of 'smg1' group and not 'smg2' sub-group
if (element.hasClass("smg1") && !element.hasClass("smg2")) {
$("#smError1").html(error);
// else if it's part of 'smg2' sub-group
} else if (element.hasClass("smg2")) {
$("#smError2").html(error);
}
},
groups: {
group1: "sm_Appreciation,sm_Impact,sm_Safety,sm_People",
group2: "sm_Parents,sm_Goals,sm_Money,sm_Decision"
}
Working DEMO: http://jsfiddle.net/2xW76/
You'll probably still need to tweak your message placement and your groups option for the exact desired effect, however, my demo shows the working logic for validation of groups within groups.

Resources