1

I have this bug I tried al the posts on StackOverflow and nothing is solving it like:

1) $rootScope Array.

2) $scope.$apply() (and after reading so much I knew it is not the best solution as it will gives an error because my input text field fire it on change so now need to use it)

3) Save the array in a service also not working

this is my code

app.factory('searchService', function() {
var searchItems= [
      "Design",
      "Graphic Design",
      "PhotoShop",
      "UI/UX Design",
      "Web Design",
      "Web Development",
      "JavaScript",
      "CSS3",
      "HTML5",
      "C#",
      "ASP.Net",
      "Bootstrap",
      "Grid System",
      "JQuery",
      "JQuery UI",
      "JQuery Mobile",
      "Front-End",
      "Back-End",
      "PHP",
      "MySQL",
      "SQL Server",
      "Branding",
      "Logo Design",
      "Business Cards",
      "Print Design",
      "Brochure Design",
      "Vector Design",
      "Facebook Posts",
      "Facebook Covers",
      "Facebook Apps Design",
      "Digital Marketing",
      "Social Media",
      "Visual Studio.Net",
      "App Design",
      "App Developemnt",
      "Mobile Apps Design",
      "Mobile Apps Development",
      "Game Design",
      "Game Development",
      "Android",
      "Android Studio",
      "iOS",
      "Windows Phone",
      "Adobe Air",
      "Hypered Apps",
      "Cordova",
      "Universal Windows Apps",
      "Actionscript 3",
      "Flash",
      "2D Animation",
      "2D Characters",
      "2D Cartoon Animation",
      "Drawing",
      "Coloring",
      "Illustrating",
      "Sketching",
      "Systems Analysis",
      "Visio",
      "Pencil Sketcing",
      "Oil Paintings",
      "Book Authoring",
      "Writing",
      "E-Learning",
      "Multimedia Design",
      "Multimedia Development",
      "Windows Application",
      "3D Design",
      "3D Modeling",
      //--------------------------------
      "Java 2SE (Comming Soon)",
      "Aniamtion (Comming Soon)",
      "Motion Graphics (Comming Soon)",
      "Video Editing & Creating (Comming Soon)",
      "Photography (Comming Soon)",
      "Videography (Comming Soon)",
      "3D Animation (Comming Soon)",
      "Music Creation (Comming Soon)"
    ];
return searchItems;
});


app.factory('items', function() {
   var property = [];
    return {
        getProperty: function () {
            return property;
        },
        setProperty: function(value) {
            property = value;
        }
    };
});

app.controller('searchCTRL', function($scope, $rootScope, searchService, sharedProperties, items){
"use strict";

setTimeout(function(){
    addClass(document.getElementsByClassName("list-wrapper").item(0), 'animateIn');
},500);

$rootScope.searchItems = searchService;

//Sort Array
//$rootScope.searchItems.sort();
//Define Suggestions List
$rootScope.suggestions = [];
$rootScope.items = items.getProperty();
//Define Selected Suggestion Item
$rootScope.selectedIndex = -1;

//Function To Call On ng-change
$rootScope.search = function(){
    $rootScope.suggestions = [];
    var myMaxSuggestionListLength = 0;
    for(var i=0;i < $rootScope.searchItems.length;i++){
        var searchItemsSmallLetters = angular.lowercase($rootScope.searchItems[i]);
        var searchTextSmallLetters = angular.lowercase($scope.searchText);
        if(searchItemsSmallLetters.indexOf(searchTextSmallLetters) !== -1 && searchItemsSmallLetters.indexOf(searchTextSmallLetters) === 0){
            $rootScope.suggestions.push(searchItemsSmallLetters);
            items.setProperty($rootScope.suggestions);
            myMaxSuggestionListLength += 1;
            if(myMaxSuggestionListLength === 5){
                break;
            }
        }
    }
    //$rootScope.items = items.getProperty();
    angular.copy(items.getProperty(),$rootScope.items)
    console.log($rootScope.items)
};

//Keep Track Of Search Text Value During The Selection From The Suggestions List  
$rootScope.$watch('selectedIndex',function(val){
    if(val !== -1) {
        $scope.searchText = $rootScope.suggestions[$rootScope.selectedIndex];
        sharedProperties.setProperty($scope.searchText);
    }
});


//Text Field Events
//Function To Call on ng-keydown
$rootScope.checkKeyDown = function(event){
    if(event.keyCode === 40){//down key, increment selectedIndex
        event.preventDefault();
        if($rootScope.selectedIndex+1 < $rootScope.suggestions.length){
            $rootScope.selectedIndex++;
        }else{
            $rootScope.selectedIndex = 0;
        }
    }else if(event.keyCode === 38){ //up key, decrement selectedIndex
        event.preventDefault();
        if($rootScope.selectedIndex-1 >= 0){
            $rootScope.selectedIndex--;
        }else{
            $rootScope.selectedIndex = $rootScope.suggestions.length-1;
        }
    }else if(event.keyCode === 13){ //enter key, empty suggestions array
        event.preventDefault();
        $rootScope.suggestions = [];
        $rootScope.selectedIndex = -1;
        sharedProperties.setProperty($scope.searchText);
        $rootScope.showPopUpContent();
    }else if(event.keyCode === 27){ //ESC key, empty suggestions array
        event.preventDefault();
        $rootScope.suggestions = [];
        $rootScope.selectedIndex = -1;
    }else{
        $rootScope.search();
    }
};

//ClickOutSide
var exclude1 = document.getElementById('textFiled');
$rootScope.hideMenu = function($event){
    $rootScope.search();
    //make a condition for every object you wat to exclude
    if($event.target !== exclude1) {
        $rootScope.suggestions = [];
        $rootScope.selectedIndex = -1;
    }
};
//======================================

//Function To Call on ng-keyup
$rootScope.checkKeyUp = function(event){ 
    if(event.keyCode !== 8 || event.keyCode !== 46){//delete or backspace
        if($scope.searchText === ""){
            $rootScope.suggestions = [];
            $rootScope.selectedIndex = -1;
        }
    }
};
//======================================

//List Item Events
//Function To Call on ng-click
$rootScope.AssignValueAndHide = function(index){
     $scope.searchText = $rootScope.suggestions[index];
     sharedProperties.setProperty($scope.searchText);
     $rootScope.suggestions=[];
     $rootScope.selectedIndex = -1;
    };  
});

index.html

<div class="list-wrapper" ng-controller="searchCTRL">
        <header>
            <h1><img class="emadzedan" src="./img/EmadZedan.png" width="123" height="123" alt="Emad Zedan"/></h1>
            <h1>Emad Morris Zedan</h1>
            <h4>Professional Web Designer,Front-End Developer, Artist & Book Author</h4>
        </header>
        <div class="label">Search for A Samples Category</div>

        <div><input type="text" autofocus placeholder="e.g. Web Design or Start With Any Letter..." id="textFiled" class="input" ng-keydown="checkKeyDown($event)" ng-keyup="checkKeyUp($event)"  ng-model="searchText" ng-change="search()" /></div>

        <ul class="suggestions-list">
            <li ng-repeat="suggestion in items track by $index" ng-class="{active : selectedIndex === $index}" ng-click="AssignValueAndHide($index)">{{suggestion}}</li>
        </ul>

        <div class="label">Search for "Design" to view all samples as "Design" is common along all samples.</div>

        <div class="buttonDiv" ng-click="showPopUpContent($index)">Search</div>
        <div class="menu">
            <div class="floatLeft"><a href="./Downloads/EmadZedanResume.pdf" target="_blank">Resume</a></div>
            <div class="floatLeft">|</div>
            <div class="floatLeft"><a href="./Downloads/EmadZedanCV.pdf" target="_blank">C.V.</a></div>
            <div class="floatLeft">|</div>
            <div class="floatLeft"><a href="http://www.emadbook.com" target="_blank">Blog</a></div>
            <div class="clearboth"></div>
        </div>
        <footer>Copyrights © 2017 for Emad Zedan</footer>
    </div>

{{Suggestion}} is empty although the list is showing items by the length of the array

css.css

@charset "utf-8";
/* CSS Document */
body{
    font-family:'Oswald', sans-serif;
    font-size:14px;
    font-weight: 300;
    margin:0px;
    padding:0px;
    color: #ddd;
    background-color: #121212;
}
.clearboth{
    clear:both;
}
.floatLeft{
    float:left; 
}
::-webkit-input-placeholder{
    color:#333;
    /*padding-left:10px;*/
}
:-moz-placeholder{ /* Firefox 18- */
    color:#333;
    /*padding-left:10px;*/
}
::-moz-placeholder{  /* Firefox 19+ */
   color:#333;
   /*padding-left:10px;*/
}
:-ms-input-placeholder{ 
   color:#333;
  /*padding-left:10px;*/
}
input{
    color:#333;
}
.list-wrapper {
    position:absolute;
    width:300px;
    height:150px;
    top:10%;
    left:50%;
    margin-left:-150px;
    opacity:0;
    transform: translateY(200px) rotateX(90deg);
    -webkit-transform: translateY(200px) rotateX(90deg);
    transition: all 0.5s cubic-bezier(0.68, -0.55, 0.26, 1.55);
    -webkit-transition: all  0.5s cubic-bezier(0.68, -0.55, 0.26, 1.55);
}
header{
    prespective:1000;
}
h1, h4{
    text-align:center;
    padding:5px;
    margin:5px; 
    line-height: normal;
}
h4{
    color:#990000;
}
.emadzedan{
    border-radius:50%;
    border:3px solid #900;
    position:relative;
    margin:5px auto;
}
.label{
    padding: 5px 10px;
    text-align: center;
    font-size: 14px;
    font-weight: 300;
    display: block;
    width: 300px;
    margin: 0 auto;
    line-height: normal;
    white-space: normal;
}
footer{
    text-align:center;
    width:100%; 
}
.menu{
    text-align:center;
    width:150px;
    left:50%;
    margin:10px auto;
}
.menu a, .menu a:visited{
    color:#ddd;
    text-decoration:none;
    display:inline-block;
    padding:0px 10px;   
}
.menu a:hover{
    color:#900;
}
.input{
    width:280px;
    height:35px;
    outline:none;
    padding:0px 10px;
    margin:0px auto;
    display:block;
    border:1px solid #ddd;
}
.suggestions-list {
    position: absolute;
    list-style-type: none;
    margin:0px;
    padding:0px;
    overflow:auto;
    z-index:2;
    margin-left:10px;
}
.suggestions-list li {
    color: #000;
    padding: 5px 10px;
    height:30px;
    cursor: pointer;
    background: #f5f5f5;
    border-left: 1px solid #ddd;
    border-right: 1px solid #ddd;
    width:280px;

}
.suggestions-list li:last-child{
    border-bottom: 1px solid #ddd;
}
.suggestions-list li:hover {
    background: #ddd;
}
.suggestions-list li:active,
.suggestions-list li.active {
    color: #FFFFFF;
    background: #900;
    width:280px;
}
.suggestions-list:focus{
    outline:none;
}
.buttonDiv{
    color: #FFF;
    background: #900;
    border:1px solid #FFF;
    padding:10px 50px;
    display:inline-block;
    border-radius:50px;
    cursor:pointer;
    text-align:center;
    max-width:50%;
    margin:10px 0px 10px 85px;
}
.buttonDiv:hover{
    color:#900;
    background:#FFF;    
    border:1px solid #900;
}
/*-----------------------------*/
.popup{
    background-color:#121212;
    height:auto;
    min-height:100vh;
    width:100%;
    position:absolute;
    left:0px;
    top:0px;
    z-index:3;
    display:none;
}
.popupHeader{
    padding:10px 0px 0px 15px;
    font-size:16px;
    color:#333;
    height:50px;
    background-color:#ddd;
    position:Fixed;
    top:0;
    left:0;
    width:100%;
    z-index:10;
}
.popupContent{
    width:90%;
    margin:50px auto;
}
.closeButton{
    color: #333;
    padding:5px 15px;
    height:30px;
    display:inline-block;
    border-radius:50px;
    cursor:pointer;
    text-align:center;
    float:right;
    font-size:64px;
    position:absolute;
    top:-25px;
    right:-5px;
    perspective: 1000px;
}
.closeButton:hover{
    color:#900;
}
.block{
    float:left;
    margin:10px 10px 0px 0px;
    width:32.6%;
    display:none;
    cursor:pointer;
    opacity:0;
    transform: translateY(200px) rotateX(90deg);
    -webkit-transform: translateY(200px) rotateX(90deg);
    transition: all 0.5s cubic-bezier(0.68, -0.55, 0.26, 1.55);
    -webkit-transition: all  0.5s cubic-bezier(0.68, -0.55, 0.26, 1.55);
}
.animateIn{
    display:block;
    opacity:1;
    transform: translateY(0px) rotateX(0deg);
    -webkit-transform: translateY(0px) rotateX(0deg);
}
.block img {
    border:5px solid #333;
    opacity:0.8;    
}
.block img:hover {
    border:5px solid #900;
    opacity:1;  
}
@media all and (max-width: 1530px){
    .block{
        float:left;
        margin:10px 10px 0px 0px;
        width:48.5%;
        display:none;
    }
}
@media all and (max-width: 800px){
    .block{
        float:left;
        margin:10px 10px 0px 0px;
        width:100%;
        display:none;
    }
}
.popupHeader .emadzedan{
    position:relative;
    top:-5px;
    border:1px solid #900;  
}
.positionSearchTerm{
    position:relative;
    left:5px;
    top:-5px;
}
.SearchTerm{
    color:#900; 
    text-transform: capitalize;
}
.details{
    background-color:#333;
    width:100%;
    min-height:100vh;
    max-height:100vh;
    display:none;
    z-index:5;
    position:fixed;
    top:0px;
    left:0px;
    prespective:1000;
}
.detailsInner{
    width:50%;
    position:absolute;
    z-index:6;
    top:10%;
    left:50%;
    margin-left:-25%;
    display:none;
    transform: translateY(500px) rotateY(90deg);
    -webkit-transform: translateY(500px) rotateY(90deg);
    transition: all 0.5s cubic-bezier(0.68, -0.55, 0.26, 1.55);
    -webkit-transition: all  0.5s cubic-bezier(0.68, -0.55, 0.26, 1.55);

}
.animateIn2{
    transform: translateY(0px) rotateY(0deg);
    -webkit-transform: translateY(0px) rotateY(0deg);
}
.animateOut2{
    transform: translateY(500px) rotateY(90deg);
    -webkit-transform: translateY(500px) rotateY(90deg);
}
.DetailsHeader{
    padding:15px 0px 15px 15px;
    font-size:16px;
    color:#333;
    height:50px;
    background-color:#ddd;
    border-top:5px solid #900;
    border-left:5px solid #900;
    border-right:5px solid #900;
}
#DetailsContent{    
    border-bottom:5px solid #900;
    border-left:5px solid #900;
    border-right:5px solid #900;
}
.closeButtonInner{
    color: #333;
    padding:5px 15px;
    height:30px;
    display:inline-block;
    border-radius:50px;
    cursor:pointer;
    text-align:center;
    float:right;
    font-size:64px;
    position:relative;
    top:-45px;
}
.closeButtonInner:hover{
    color:#900;
}

This is a snapshot shot of the design to make see the result on my PC:

enter image description here

11
  • Can you post the result of console.log($rootScope.items) at the end of $roootScope.search? I made a plunkr with your code and replaced the parts that you didn't post with mock values and it works. Commented Nov 5, 2016 at 10:41
  • ["web design", "web development", "windows phone", "writing", "windows application"] this is the result in the console but still do not bind Commented Nov 5, 2016 at 10:44
  • It still works for me with these values - $rootScope.$apply() might be necessary if $rootScope.search() was called outside of angular scope. Another thing that might help is using angular,copy(items.getProperty(),$rootScope.items) since that does not replace the object reference Commented Nov 5, 2016 at 11:04
  • angular.copy(items.getProperty(),$rootScope.items) this statement is giving an error "Can't copy! Source and destination are identical" and if I want to use $apply where should i use it or how do i know that search() is called outside of the angular scope?? Commented Nov 5, 2016 at 11:11
  • angular.copy(items.getProperty(),$rootScope.items) should be called instead of $rootScope.items = items.getProperty() . In my code, I called $rootScope.search() from setTimeout(), which does not trigger a digest cycle, so I put a $rootScope.$apply() at the end of $rootScope.search() Commented Nov 5, 2016 at 11:13

3 Answers 3

1

I found the correct solution for it:

<ul class="suggestions-list">
                <li ng-repeat="suggestion in items track by $index" ng-class="{active : selectedIndex === $index}" ng-click="AssignValueAndHide($index)" data-ng-bind="suggestion"></li>
 </ul>

data-ng-bind="suggestion" insted of {{suggestion}}

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

0

you must use track by $index for such array. check this angular documentation

 <div ng-repeat="n in suggestions track by $index">
      {{n}}
    </div>

this might help you.

Comments

0

Heloo Emad, I got the problem you are facing. Even I faced this problem and I got the solution from the article Facing problem with ng-Repeat . The best part is , they just don't give the solution but also the reason why it happens.

For better understanding , you can also find a youtube video which explains everything.

Hope it works for you too.

6 Comments

it is saying that I should use the track by $index and as the previous answer I'm using it already, can you point me to a specific youtube video that says something not about the track by index as it has been 2 days searching on the net and I did not find a solution
yea it is saying about adding track by index, but that's just one of the way . Based on your object in an array you can use other properties also to solve this issue.
check out this video , it may help you [link] (youtube.com/watch?v=KMrD4bxbgxQ&feature=youtu.be)
sorry i did not notice the youtube video at the end i will watch it and see
I watched the video and it say nothing but adding track by index also the problem that the article and the video are solving is talking about not render items but my code renders Items and the Autocomplete list I'm creating is generated and it assigns value to text input but the suggestion value is not rendered in the list I will add more of my code might help others to understand my situation
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.