I am displaying all of the articles from the database and I've created a simple text search for it.
<input ng-model="searchText" placeholder="Search for articles" class="search-text">
And I am filtering the content from the searchText
<section class="articles" ng-repeat="contentItem in content | filter:searchText">
Now what I'm trying is to have buttons with the categories and tags from my database and to be able to filter the content based on the button values.
<span ng-repeat="category in categories">
<button ng-click="searchText = '{{category.local.name}}'" class="btn btn-primary">{{ category.local.name }}</button>
</span>
The code above is not working but for example if I'm taking out the ng-repeat and type all the categories myself it will work:
<span>
<button ng-click="searchText = 'some text'" class="btn btn-primary">Some text</button>
</span>
My question is how can be the good way to pass the content from the search input and buttons to the filter method?
Here is the full code:
<div class="container">
<h1>List of articles</h1>
<section class="search-items">
<input ng-model="searchText" placeholder="Search for articles" class="search-text">
<div class="row">
<div class="col-sm-6">
<h6>Search based on categories:</h6>
<span ng-repeat="category in categories">
<input type="button" ng-click="searchText = '{{ category.local.name }}'" value="{{ category.local.name }}" class="btn btn-primary">
</span>
</div>
<div class="col-sm-6">
<h6>Search based on tags:</h6>
<span ng-repeat="tag in tags">
<input type="button" ng-click="searchText = '{{tag.local.name}}'" value="{{ tag.local.name }}" class="btn btn-primary">
</span>
</div>
</div>
</section>
<section class="articles" ng-repeat="contentItem in content | filter:searchText">
<article class="well">
<h3>{{ contentItem.local.title }}</h3>
<p>{{ contentItem.local.content }}</p>
<span><b>Article author: {{ contentItem.local.author }}</b></span><br/>
<span class="label label-primary">{{ contentItem.local.categories.category }}</span>
<span class="label label-primary">{{ contentItem.local.tags.tag }}</span>
</article>
</section>
</div>
angular.module('myApp', [])
.controller('ThingsController', function(){
var ctrl = this;
ctrl.things = ['thing 1', 'thing 2', 'another thing']
ctrl.searchText = "something"
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<div ng-app="myApp" ng-controller="ThingsController as thingCtrl">
<div ng-repeat="thing in thingCtrl.things">
<button ng-click="thingCtrl.searchText = thing">{{thing}}</button>
</div>
<pre>{{thingCtrl.searchText}}
Above snippet shows it working also using controller as syntax. Typically you don't want to use the $scope as though it's your model you want it to point to your model otherwise you may run into some weird prototypical inheritance problems. As in $scope.myModel = {someProp:4} instead of $scope.someProp = 4 using the controller as syntax also avoids this issue.
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
Related
I am using vue pretty checkbox to display a checkbox. However, based on if one of the checkboxes is checked or not my content has to change! So, I need something like a listener on those vue pretty checkbox components.
However, because vue pretty checkbox is a package I cannot modify the code. My question now is, how can I listen on those checkboxes if they have changed from another component.
Because the products-manager component gets the values. So, whenever the values of the checkboxes of the p-check inside the product-filter changes, I need to pass that to the products-manager component in order to reload the data!
Any ideas on how I can do this? I have already tried this and this but those aren't working for me...
Very important: The number of checkboxes is dynamically as you can see below. The first two checkboxes are always there but the checkbox below gets genereated by a v-for!
This is my sourcecode so far (home template):
<div id="home" class="row">
<div class="col-xl-12" id="product-sort-and-filter">
<products-filter ref="productsFilter" :product-types-prop="{{ json_encode($productTypes) }}"></products-filter>
</div>
<div class="col-xl-9">
<div class="products">
<products-manager ref="productsManager" :products-prop="{{ json_encode($products) }}" auth="{{ \Illuminate\Support\Facades\Auth::check() }}" :userprop="{{ json_encode(\Illuminate\Support\Facades\Auth::user()) }}" route="{{ route('product.index') }}"></products-manager>
</div>
</div>
<div class="col-xl-3">
<sidebar-manager ref="SidebarManager" :top-products-today-prop="{{ json_encode($products) }}" :top-products-week-prop="{{ json_encode($products) }}" :top-products-month-prop="{{ json_encode($products) }}"></sidebar-manager>
</div>
</div>
products filter component:
<template>
<div class="product-sort-and-filter-wrapper d-flex">
<div class="col-xl-9 product-sorting no-padding">
<ul class="list-inline">
<li class="list-inline-item">Highlights</li>
<li class="list-inline-item">Aktuell</li>
<li class="list-inline-item">Diskutiert</li>
</ul>
</div>
<div class="col-xl-3 product-filter no-padding text-right">
<div class="dropdown d-inline-flex">
<i class="fas fa-filter"></i>FILTERN
<div class="dropdown-menu" style="margin-top: 0px">
<div class="productTypesBoxes dropdown-item pretty-checkbox-wrapper">
<p-check name="productExpiredCheckbox" class="p-svg p-plain p-bigger p-smooth" ref="showExpired" toggle true-value false-value>
<span class="checkbox-label on rubik-medium">Abgelaufene anzeigen</span>
<label slot="off-label"><span class="checkbox-label off rubik-medium">Abgelaufene anzeigen</span></label>
<span slot="extra" class="svg"><i data-feather="check-square"></i></span>
<span slot="off-extra" class="svg"><i data-feather="square"></i></span>
</p-check>
</div>
<div class="dropdown-divider"></div>
<div class="productTypesBoxes dropdown-item pretty-checkbox-wrapper">
<p-check name="productTypeCheckbox" class="p-svg p-plain p-bigger p-smooth" ref="showAllProductTypes" toggle true-value false-value checked>
<span class="checkbox-label on rubik-medium">Alle anzeigen</span>
<label slot="off-label"><span class="checkbox-label off rubik-medium">Alle anzeigen</span></label>
<span slot="extra" class="svg"><i data-feather="check-square"></i></span>
<span slot="off-extra" class="svg"><i data-feather="square"></i></span>
</p-check>
</div>
<div class="productTypesBoxes sub dropdown-item pretty-checkbox-wrapper" v-for="productType in productTypes">
<p-check name="productTypeCheckbox" :value="productType.id" class="p-svg p-plain p-bigger p-smooth" :ref="'productType' + productType.id" toggle>
<span class="checkbox-label on ">{{ productType.label }}</span>
<label slot="off-label"><span class="checkbox-label off ">{{ productType.label }}</span></label>
<span slot="extra" class="svg"><i data-feather="check-square"></i></span>
<span slot="off-extra" class="svg"><i data-feather="square"></i></span>
</p-check>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "ProductsFilter",
props: ['productTypesProp'],
data() {
return {
highlights: true,
aktuell: false,
diskutiert: false,
showExipredDeals: false,
productTypes: this.productTypesProp
}
}
}
</script>
<style scoped>
</style>
I’m starting with vue js and I’m listing some data from database. More specifically posts with title, description and images.
I have Edit and Delete buttons. All posts are loaded using v-for. So when I click to edit one post, all the posts are “openning” to be edited.
I need to open the editing only in one post at a time. I mean, the specific post I really want to edit.
I made some progress with title input and with image delete badge but still need to work on Save and Cancel buttons (they open in all posts) and input files (when I choose files in second post for example, they load into first post).
<div id="app" class="row mb-50">
<div v-for="(item, index) in tours" v-bind:key="item.id" id="tours" class="col-md-12 mb-30">
<div class="tour-list">
<div class="tour-list-title">
<p>
<!-- here I can block input title to be disabled on other posts not than the specific one and I intend to do the same with textarea -->
<input class="inputEdit" type="text" ref="item.id" v-model="item.title"
:disabled="editingTour !== item.id" :class="{inputEditOpen: !editingTour}" />
</p>
</div>
<div class="tour-list-description">
<p>
<textarea class="inputEdit" :disabled="!editingTour" v-model="item.description"
:class="{inputEditOpen: !editingTour}">
{{ item.description }}
</textarea>
</p>
</div>
<div class="tour-list-pics">
<div class="row mb-20">
<div class="col-md-12">
<ul class="pics-list">
<li v-for="(image, index) in item.images">
<!-- here I could hide badge -->
<span :hidden="editingTour !== item.id" class="badge"
#click="$delete(item.images, index), deleteImage(image.imageID)">
<i class="fa fa-fw fa-times-circle"></i>
</span>
<div class="pics-list-image-container img-fluid cursor-pointer"
v-bind:style="{'background-image': 'url(http://localhost/tours/'+image.image + ')' }"
#click="openModal = true, showModal(image.image)">
</div>
</li>
<li v-if="urls" v-for="(url, key) in urls" :key="key">
<div id="preview" :ref="'url'" class="pics-list-image-container img-fluid"></div>
</li>
<li v-if="editingTour" class="add-pics-item">
<div :hidden="editingTour !== item.id" class="mt-10">
<label for="file-upload" class="custom-file-upload">
<img class="img-fluid" src="./img/plus-icon.png">
</label>
<input id="file-upload" type="file" #change="onFileChange"
name="files[]" multiple />
</div>
</li>
</ul>
</div>
</div>
</div>
<div class="tour-list-options">
<div class="row">
<div class="col-md-6">
<span>
<button #click="editingTour = item.id" v-if="!editingTour"
class="btn border btn-circle tour-list-edit-btn">Edit</button>
</span>
<span>
<button #click="editTour(item)" v-if="editingTour"
class="btn border btn-circle tour-list-edit-btn">Save</button>
</span>
<span>
<button #click="clearInput" v-if="editingTour"
class="btn border btn-circle tour-list-delete-btn">Cancel</button>
</span>
<span>
<button #click="deleteTour(item.id, index)" v-if="!editingTour"
class="btn border btn-circle tour-list-delete-btn">Delete</buton>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
Update
If I use
<button #click="editTour(item)" v-if="editingTour == item.id" class="btn border btn-circle tour-list-edit-btn">Save</button>
all others Save buttons get hidden.
I think you can use add to each object of list new property isEditing and look for it in each item of the loop to check Save/Edit show.
Now your one prop editingTour can't be used for multiple edit, it can't store array of edited items id.
Template of buttons would look like:
<span>
<button #click="item.isEditing = item.id" v-if="!item.isEditing"
class="btn border btn-circle tour-list-edit-btn">Edit</button>
</span>
<span>
<button #click="editTour(item)" v-if="item.isEditing"
class="btn border btn-circle tour-list-edit-btn">Save</button>
</span>
<span>
<button #click="clearInput(item)" v-if="item.isEditing"
class="btn border btn-circle tour-list-delete-btn">Cancel</button>
</span>
<span>
<button #click="deleteTour(item.id, index)" v-if="!item.isEditing"
class="btn border btn-circle tour-list-delete-btn">Delete</button>
</span>
Please check the image for reference
The editable div is added using tags and text. Text is inputted by the user. The tags are selected from the two boxes above them.
When the data in the tags is changed then the tags selection list data is also changed accordingly.
But the data in the content-editable div remains same. I need it to also change accordingly or notify missing when deleted.
I am using Meteor JS and Blaze , React for this . I took some reference from this fiddle link
"click .selectable-tags"(e, t) {
// sets the tags inside the Method box on click
let el = e.target.cloneNode(true);
el.setAttribute('contenteditable', false);
document.querySelector('[contenteditable]').appendChild(el);
},
<div class="recipe_create_form_input_lable">Ing</div>
<div class="ingredients-list">
{{#each ing}}
<div class="ingredients-div" id="ing_parent_{{#index}}">
<div class="ing-list-box-left">
<input type="text" value="{{this}}" placeholder="Ing " class="ree-create-text_box_rectangle ingredient_input" id="ing_{{#index}}"> <span class="timeLable"></span>
</div>
<div class="ings-list-box-right">
<button type="button" class="btn btn-default delete-ing-btn" style="margin-left : 5px;">
<!-- <img src="/images/remove-copy-2.svg" style="width:30px;"/> -->
<label style="width:30px;height: 18px;">x</label>
</button>
</div>
</div>
{{/each}}
</div>
{{#each stepList}}
<div class="step-div" id="step_{{#index}}">
<div class="step-list-box-left">
<div class="rec_create_form_input_lable stepLabel">Step {{getStepNo(#index)}}</div>
<div value="{{this}}" id="step_input_{{#index}}" name="step" class="rec-create-text_box_rectangle stepbox step_input" contenteditable="true"></div>
</div>
<div class="step-list-box-right">
<button type="button" class="btn btn-default delete-step-btn" style="margin-left : 5px;">
<label style="width:30px;height: 18px;">x</label>
</button>
</div>
</div>
<div class="showbiz">
<div class="custom-input">
<div class="selectable-tags">
{{#each ing }}
<span style=" background: #E1ECF4;border: 1px dotted #39739d;" class="ingredients-tags"> {{this}} </span>
{{/each}}
</div> </div>
</div>
{{/each}}
<div>
I'm quire new to Angular so I apologise if this has already been answered but I just couldn't figure it out when I see other uses for it.
I am using a REST API to simply fetch some news articles from an external URL and print them out nicely on a news listing page.
Link for results
(You can see the output of the JSON in the console)
The JSON that is returned looks like this (just showing one set):
[
{
"author":"Napier Lopez",
"title":"Report: First real Samsung Galaxy S8 photo and release date leaked",
"description":"Ever-reliable leaker Evan Blass of Venture Beat has just given us our best look at Samsung’s Galaxy S8 yet. The report confirms several of the details we’ve already learned about the device, as well as providing an announcement and release date. Blass confirms that the devices are foregoing the front fingerprint scanner for one place on …",
"url":"https://thenextweb.com/mobile/2017/01/26/report-first-real-samsung-galaxy-s8-photo-release-date-leaked/",
"urlToImage":"https://cdn3.tnwcdn.com/wp-content/blogs.dir/1/files/2017/01/Samsung-Galaxy-S8-Blur-not-real.jpg",
"publishedAt":"2017-01-26T22:13:13Z"
} ...
]
Here is my how I've printed out each news article:
app.js:
/* Newsfeed API Call */
var app = angular.module('newsFeed', [])
.controller('Newsfeed', function($scope, $http) {
$http.get('https://newsapi.org/v1/articles?source=the-next-web&sortBy=latest&apiKey=6ddf8d3cc8a54cc0abf89ad7d685da54').
then(function(response) {
$scope.news = response.data;
});
});
news-listing.html:
<div class="container" ng-controller="Newsfeed">
<br/>
<form>
<div class="col-md-6">
<h2>Newsfeed</h2>
<br/>
<div class="form-group">
<input type="text" class="form-control" ng-model="searchText" name="search-news" id="search-news" placeholder="Search for news">
</div>
<div class="form-group">
<select class="custom-select" ng-model="selectedAuthor" ng-options="n.author for n in news.articles | unique: 'author'">
<option ng-click="selectedAuthor = undefined" value="">Filter by Author</option>
</select>
</div>
</div>
</form>
<div>
<div class="card" style="width: 20rem;" ng-repeat="n in news.articles | filter:searchText | filter:selectedAuthor">
<img class="card-img-top img-responsive" src="{{n.urlToImage}}" alt="Card image cap">
<div class="card-block">
<h4 class="card-title">{{n.title | cut:true:50:' ...'}}</h4>
<p class="card-text"> {{n.author}} <small>on {{ formatDate(n.publishedAt) | date:'MM/dd/yyyy'}}</small> </p>
<p class="card-text"> {{n.description | cut:true:100:' ...'}}</p>
<a class="btn btn-primary" href="#" role="button"><i class="fa fa-thumbs-up" aria-hidden="true"></i></a>
<a class="btn btn-danger" href="#" role="button"><i class="fa fa-thumbs-down" aria-hidden="true"></i></a>
</div>
</div>
</div>
</div>
What I want is that for each news article in the news-listing I can click on it to see more details, so I would have an articles-details page that would take some sort of unique identifier and use that to pull out all of the data.
How can I achieve this baring in mind that the response in the JSON for the articles does not contain any sort of unique ID?
Inside your ng-repeat there is an angular variable: $index which gives you the position of the element in the array (news.articles). You can use it in order to access to the n element in the array.
So, you would have a function which you would call on you view button like this:
$scope.view = function (idx){
//get the n-esim article inside the array like something like
var element = $scope.news[idx] //and do some stuff with element
}
... and in your view you would have something like
<div class="card" style="width: 20rem;" ng-repeat="n in news.articles | filter:searchText | filter:selectedAuthor">
<!--...-->
<a class="btn btn-primary" role="button" ng-click="view($index)">Details</a>
<!--...-->
<a class="btn btn-primary" href="#" role="button"><i class="fa fa-thumbs-up" aria-hidden="true"></i></a>
<a class="btn btn-danger" href="#" role="button"><i class="fa fa-thumbs-down" aria-hidden="true"></i></a>
</div>
</div>
I make my own autocomplete in html, I use ng-repeat to show the suggestion. this is the code:
<div content-for="title">
<span>Add Friend</span>
</div>
<div class="scrollable">
<div class="scrollable-content">
<div class="list-group">
<div class="list-group-item">
<form class="form-inline" role="form">
<div class="form-group">
<label class="sr-only" for="exampleInputEmail2">Email</label>
<input type="text" class="form-control" data-ng-model="add.email" id="exampleInputEmail2" placeholder="Email" auto-complete autocomplete="off"/>
<div href="#" ng-repeat="x in cobas | filter:add.email">
<div class="media-body" ng-if="add.email.length > 0">
<h5 class="list-group-item media">{{x.name}}
</div></div>
</div>
<button type="submit" class="btn btn-default" data-ng-click="addfriends()">Add</button>
</form>
</div>
</div>
</div>
</div>
what I want is, when I click the suggestion result, the value of that textbox is change to the suggestion result using ng-click, can someone help me?
You have to add function in your controller, like below:
$scope.autocomplete = function (completeText) {
$scope.add.email = completeText;
};
and then in html call the function on ng-click like below,
<div href="#" ng-repeat="x in cobas | filter:add.email" ng-click="autocomplete(x.name)">
<div class="media-body" ng-if="add.email.length > 0">
<h5 class="list-group-item media">{{x.name}}</h5
</div>
</div>